Bash
1. Wstęp
2. Historia
3. Skróty klawiaturowe
4. cd: przejście pomiędzy katalogami
5. Historia wiersza poleceń
6. Etapy procedury przetwarzania polecenia (uproszczone)
7. Strumień wyjściowy
8. Strumień wejściowy
9. Polecenia
9.1. Aliasy
9.2. Zadania (ang. jobs)
10. Skrypty
10.1. Wykonywanie poleceń
10.2. Zmienne
10.2.1. Tablice
10.3. Wyrażenia arytmetyczne
10.4. Konstrukcje składniowe
10.5. Funkcje
10.6. Sygnały
11. Konfiguracja
11.1. Pliki startowe
11.2. Ciekawe zmienne środowiskowe
11.3. Prompty
11.4. readline
11.5. shopt
11.6. set
11.7. Inne
12. Zadania administracyjne
13. Bezpieczeństwo
14. Często popełniane błędy
15. Przenośność skryptów
15.1. Różnice między Bashem a Sh
16. Inne
17. Literatura
Wstęp
Wiersz poleceń (w praktyce: Bash) jest jednym z najczęściej używanych przez programistów narzędzi Linuksa, zwłaszcza w połączeniu z SSH.
Notatki są przeznaczone raczej dla średniozaawansowanych użytkowników Basha, pochodzą ze szkolenia z dnia 11.01.2010 (opartego głównie na książce wymienionej w bibliografii) i zostały uzupełnione w póżniejszym terminie notatkami z lektury manuala.
Historia
Drzewko „dziedziczności” powłok przedstawia poniższy rysunek.
sh Powłoka Bourne'a (System V) ksh Powłoka Korne'a tksh Tcl + Korn zsh bash Bourne Again Shell csh Powłoka C (BSD) tcsh
Zaawansowani użytkownicy Linuxa często cenią sobie wysoko powłokę zsh
.
Skróty klawiaturowe
Skróty klawiaturowe w Bashu są zaczerpnięte z edytora Emacs (często zamiast Esc można użyć lewego Alt, jeśli window manager (KDE, GNOME), na to pozwala). Niektóre polecenia można wywołać a argumentem numerycznym (który zwykle oznacza wielokrotne wykonanie polecenia) – wtedy należy poprzedzić polecenie liczbą wprowadzoną z wciśniętym klawiszem Alt.
Najciekawsze polecenia:
Ctrl+K | Usunięcie wszystkich znaków do końca wiersza | Ctrl+U | Usunięcie wszystkich znaków do początku wiersza |
Ctrl+L | Wyczyszczenie ekranu i powtórne wyświetlenie wiersza | Ctrl+O | To samo co naciśnięcie Enter i wyświetlenie kolejnego wiersza z historii |
Ctrl+R | Wyszukiwanie przyrostowe wstecz w historii | Ctrl+S | Wyszukiwanie przyrostowe w przód w historii |
Ctrl+T | Zamiana pozycji dwóch znaków | Esc+T | Zamiana dwóch słów miejscami |
Ctrl+V | Dosłowne zapisanie kolejnego wprowadzanego znaku | Ctrl+X Ctrl+V | Wyświetlenie informacji o wersji Basha |
Ctrl+_ | Undo | Esc+D | Usunięcie słowa przed kursorem |
Esc+B | Przesunięcie kursora o jedno słowo wstecz | Esc+F | Przesunięcie kursora o jedno słowo w przód |
Esc+L | Zamiana liter w słowie przed kursorem na małe | Esc+U | Zamiana liter w słowie przed kursorem na duże |
Esc+< | Przejście do pierwszego wiersza pliku historii | Esc+> | Przejście do ostatniego wiersza pliku historii |
Esc+. | Wstawienie ostatniego słowa poprzedniego polecenia; z argumentem n: wstawia n-te słowo poprzedniego polecenia | Esc+C | Zmiana słowa znajdującego się przed kursorem tak, aby zaczynało się wielką literą |
Esc+Tab | Próba uzupełnienia słowa danymi zapisanymi w wierszu poleceń | Ctrl+X e | Wykonanie ostatnio zdefiniowanego makra klawiatury |
Ctrl+X ( | Rozpoczęcie definicji makra | Ctrl+X ( | Zakończenie definicji makra |
Esc+Ctrl+E | Podmiana wartości aliasu, polecenia historycznego i podstawienie wartości w bieżącym wierszu | Ctrl+D | (gdy wiersz wprowadzania pusty) – wyjście z shella |
cd
: przejście pomiędzy katalogami
export CDPATH=.:..:../..:~/:~/katalog_dowiazan
- Zmienna
$CDPATH
przechowuje listę rozdzielanych znakami dwukropka nazw katalogów, które są przeszukiwane przez wbudowane poleceniecd
. Pełni ona taką samą funkcję dla instrukcjicd
, jak zmienna$PATH
dla uruchamianych skryptów. W przykładzie często używane nazwy katalogów w wartości zmiennej;katalog_dowiązań
oznacza katalog przechowujący jedynie dowiązania symboliczne do innych często wykonywanych katalogów cd
- przejście do katalogu domowego
cd ~piotrek
- przechodzi do katalogu domowego użytkownika
piotrek
cd -
- przejście do poprzedniego katalogu (sprzed poprzedniego wykonania
cd
) pushd nowy_katalog
- zapisanie dotychczasowego katalogu na stosie i przejście do nowego katalogu
dirs -v
- wyświetla aktualny stos katalogów
pushd +2
- przeniesienie na szczyt stosu wpisu o numerze 2 i jednoczesna zmiana bieżącego katalogu na odpowiadający temu wpisowi
Historia wiersza poleceń
!-4
- powtórz czwarte polecenie od końca
!string
- powtórz najświeższe polecenie rozpoczynające się łańcuchem string
!?string?
- powtórz najświeższe polecenie zawierające (gdziekolwiek) łańcuch string
^napis1^napis2^
- powtórz ostatnie polecenie z podmienionym
napis1
nanapis2
!20:p
- tylko wyświetla polecenie o nrze 20, bez wykonywania go
!:1
- pierwszy argument ostatniego polecenia
!$
- ostatni argument ostatniego polecenia (to samo co
!:$
, patrz także skrót klawiaturowyEsc+.
) !*
- wszystkie argumenty poprzedniego polecenia
history -c
- czyści całą historię
HISTSIZE
- liczba przechowywanych (w pamięci) wierszy historii (domyślnie 500)
HISTFILESIZE
- liczba przechowywanych w pliku
~/.bash_history
wierszy historii (domyślnie 500); gdy interaktywna sesja Basha kończy pracę,$HISTSIZE
wierszy historii jest kopiowanych do pliku (lub dopisywanych na końcu jeśli ustawiona jest opcjahistappend
), po czym plik jest przycinany doHISTFILESIZE
wierszy shopt -s histappend
- wymusza dopisywanie historii użytych poleceń na końcu pliku historii przy kończeniu pracy interaktywnej sesji Basha
export HISTTIMEFORMAT='%Y-%m-%d_%H:%M:%S '
- (od Basha 3.0) powoduje że wraz z poleceniem w historii będzie pamiętany (i zapisywany do pliku historii) czas jego wykonania; polecenie
history
wyświetli czas wydania każdego polecenia w podanym formacie
Etapy procedury przetwarzania polecenia (uproszczone)
- Podział na składowe rozdzielone znakami ; ( ) <> | &
- Rozwijanie aliasu
- Podstawienie tyldy
- Podstawienie wartości zmiennych
- Podstawienie wyniku polecenia (odwrotne ciapy)
- Podstawienie wyniku wyrażenia arytmetycznego
- Podział na słowa (separatorem jest spacja)
- Rozwinięcie ścieżek dostępu (*, ?, itp.)
- Odszukanie i wykonanie polecenia
W podwójnych ciapach wykonywane są kroki 4, 5 i 6. Tekst ujęty w pojedyncze ciapy opiera się wszystkim przekształceniom.
Przykład:
Kawałek skryptu:
STRONA="ls | less" $STRONA
Wyświetli komunikat błędu:
ls: |: No such file or directory ls: less: No such file or directory
Ale jeśli napiszemy:
STRONA="ls | less" eval $STRONA
wówczas uzyskamy pożądany rezultat (stronicowany listing bieżącego katalogu).
Strumień wyjściowy
2>&1
=== >&
=== &>
{ pwd; ls; cd ../gdzies; pwd; ls; } > /tmp/wszystko.txt
- Nawiasy klamrowe muszą być otoczone znakami spacji, a na końcu ostatniego grupowanego polecenia musi być średnik. Opcjonalnie można wykorzystać znaki nawiasu okrągłego, nakazując interpreterowi wykonanie poleceń w podpowłoce.
echo opcja $OPTSTR >&5
- wypisanie wyniku na 5ty deskryptor
skrypt 3>&1 1>&2 2>&3-
- zamienia deskryptory 1 i 2 przy użyciu pomocniczego deskryptora 3 (usuwanego potem)
skrypt 3>&1 1>dziennik.stdout 2>&3- | tee -a dziennik.stderr
- zamienia stderr i stdout tak aby można było kierować dane ze strumienia stdout do pliku dziennika, a informacje ze strumienia stderr zarówno na ekran jak i do pliku
>&-
- zamknięcie stdout
stdout jest buforowany, stderr nie (komunikaty o błędach widoczne są natychmiast)
Kolejność operacji przekierowania jest bardzo istotna. Porównajmy dwa poniższe polecenia:
polecenie >plik 2>&1 polecenie 2>&1 >plik
W pierwszym przypadku stdout jest skierowany do pliku, a stderr w to samo miejsce co stdout – wszystkie dane wynikowe zostaną więc zapisane do pliku. W drugim przypadku rezultat jest inny: stderr jest skierowany do stdout (który na tym etapie działania instrukcji odnosi się do ekranu!), a następnie stdout zostaje skierowany do pliku. W efekcie tylko stdout zostanie skierowany do pliku, a stderr będzie wyświetlany na ekranie.
Jednak kolejność ta musi być odwrócona w zadaniach bazujących na mechanizmie potoku. Nie można przecież umieścić operatora przekierowania za symbolem potoku, ponieważ za operatorem potoku zapisane jest następne polecenie. Powłoka czyni więc wyjątek podczas realizacji instrukcji:
polecenie 2>&1 | innepolecenie
(począwszy od Bash 4 można napisać polecenie |& innepolecenie
).
Efektem ubocznym takiego sposobu działania jest to że nie ma możliwości przekazania do potoku jedynie stderr – przynajmniej jeśli nie zamieni się uprzednio deskryptorów plików.
Przekierowanie stderr na czas działania bloku instrukcji:
# zachowanie starego deskryptora stderr exec 3>&2 # skierowanie stderr do pliku dziennika exec 2> plik_logow.txt # tutaj instrukcje, ktorych strumien stderr zostal globalnie przekierowany do pliku # przywrocenie standardowego strumienia stderr i zamkniecie deskryptora 3 exec 2>&3-
Strumień wejściowy
Sposób na umieszczanie łańcuchów wielowierszowych w skrypcie:
grep $1 <<'EOF' napisy EOF
0<&-
- zamknięcie stdin
diff <(ls /etc/rc2.d) <(ls /etc/rc3.d)
- przykład na wstawienie wyników poleceń tam gdzie program oczekuje nazw plików; sprawdź z ciekawości wynik polecenia
echo <(/bin/true)
Polecenia
type identyfikator
- określa czy identyfikator jest poleceniem wbudowanym, funkcją, aliasem, czy zewnętrznym programem; pokazuje również czy polecenie jest zhaszowane (bash najpierw sięga do hasza, a dopiero w następnej kolejności szuka w katalogach określonych w zmiennej
PATH
) builtin echo
- uruchamia polecenie wbudowane (bez względu na to czy istnieje funkcja, alias lub polecenie zewnętrzne o tej samej nazwie)
command echo
- uruchamia polecenie zewnętrzne ignorując aliasy i funkcje o tej samej nazwie
echo
- uruchamia na pewno nie alias
Aliasy
alias
- wyświetla listę wszystkich zdefiniowanych aliasów
alias terms='watch -n 1 w -hs'
- tworzy alias (bardzo ważne są pojedyncze cudzysłowy); podstawienie wykonywane jest tylko raz więc nie ma obawy o nieskończone cykle
unalias ll
- usuwa definicję aliasu
Doświadczenie uczy, że opracowując skrypt nie powinno się polegać na aliasach. Aliasy nie obsługują parametrów ($1
itp.)
Zadania (ang. jobs)
Każde polecenie na czas wykonania otrzymuje od Basha swój numerek porządkowy (wyświetlany na konsoli gdy zlecimy wykonanie polecenia w tle) do którego możemy potem się odwołać za pomocą notacji %n
. Polecenie pierwszoplanowe możemy na ogół wstrzymać kombinacją klawiszy Ctrl+Z
.
Proces uruchomiony w tle który próbuje czytać z terminala lub pisać na terminal, dostaje sygnał SIGTTIN (zwykle usypia proces).
bg %1
- wznawia wykonanie pierwszego zadania w tle
fg %1
- wznawia wykonanie pierwszego zadania na pierwszym planie
jobs
- wyświetla listę zadań (procesów wykonywanych przez Basha na rzecz użytkownika)
disown -h %1
- powoduje że przy kończeniu pracy shella do joba %1 nie będzie wysyłany sygnał SIGHUP.
Skrypty
Wykonywanie poleceń
first; second; third # sekwencyjne, kod błędu bez znaczenia first && second && third # sekwencyjne, następne wtw gdy poprzednie OK first & second & third # równoległe
- Zapis
$(pwd)
jest bardziej uniwersalną odmianą`pwd`
(konstrukcje$(...)
można np. zagnieżdżać)
Warto stosować operator &&
zamiast if
:
cd tymczasowy if (( $? )); then rm *; fi # sprawdź kod błędu
jest tym samym co:
cd tymczasowy && rm *
Użycie ||
:
polecenie || printf "%b" "Polecenie zakończone błędem, radź sobie samn" polecenie || { printf "%b" "Błądn"; exit 1; }
Zmienne
$FN
zapisujemy również jako${FN}
- Jeśli parametr zawiera spacje, to lepiej jest pisać „${1}” niż ${1}
$*
- tablica parametrów skryptu
"$@"
- tablica parametrów skryptu – każdy ujęty w cudzysłowy (na wypadek gdyby zawierały znaki spacji)
${#}
- liczba parametrów skryptu
${#VAR}
- długość ciągu przechowywanego w zmiennej
VAR
for FN in "$@" do ls -al "$FN" done
${1:-"/tmp"}
- parametr 1, a jeśli nie ma lub wartość pusta to „/tmp”
${HOME:="$(pwd)"}
- nadaj wartość jeśli nie ma lub pusta, zwróć wartość zmiennej
${HOME="/tmp"}
- nadaj wartość tylko wtedy gdy zmienna jest niezdefiniowana, zwróć wartość zmiennej
${NAZWA:3:10}
- zwraca podciąg wartości zmiennej
NAZWA
o długości 10 znaków począwszy od pozycji 3 (pozycje numerujemy od zera) ${FOO^}
- wartość zmiennej gdzie pierwsza litera będzie duża (
^^
oznacza wszystkie duże, przecinek oznacza pierwsza mała, dwa przecinki – wszystkie małe) – od Bash 4.0 FILEDIR=${1:?"Błąd. Musisz określić katalog początkowy"}
- rzuca błąd gdy nie zmienna nie zdefiniowana
mv "${FN}" "${FN/.txt/.html}"
- zmień nazwy plików z *.txt na *.html
Tablice
Zmienna w Bashu może również przechowywać tablicę (indeksowaną liczbami naturalnymi) oraz tablicę asocjacyjną (indeksowaną łańcuchami, począwszy od Bash 4).
my_arr=(misio pysio)
- inicjuje tablicę dwoma elementami
panstwa=([pl]=Polska [en]="Wielka Brytania")
- inicjuje mapę dwoma parami
${panstwa[pl]}
- odwołanie do elementu mapy (elementy tablicy indeksujemy od 0)
${my_arr[@]}
- łańcuch zawierający elementy tablicy rozdzielone spacjami i ujęte w cudzysłowy
$my_arr
- pierwszy element tablicy
${#my_arr[0]}
- liczba znaków pierwszego elementu tablicy
${#my_arr[@]}
- liczba elementów tablicy
unset my_arr[1]
- usuwa drugi element tablicy
mapfile TABLICA
- wczytuje wiersze z stdin do wskazanej tablicy
Wyrażenia arytmetyczne
let COUNT+=5 # nie może być spacji wewnątrz wyrażenia, nie ma $ przed nazwą zmiennej (z wyj. $1) COUNT=$(( COUNT + 5 ))
Bash nie umożliwia wykonywania obliczeń z wykorzystaniem liczb zmiennoprzecinkowych (w odróżnieniu od Ksh i Zsh).
Konstrukcje składniowe
Warto wyrobić sobie nawyk dodawania białych spacji pomiędzy poszczególnymi tokenami (zwłaszcza zawierającymi nawiasy) – czasami są konieczne. Alternatywą dla średnika w poniższych konstrukcjach jest znak końca wiersza.
if lista; then lista; elif lista; then lista; ... else lista; fi if (( $# = 3.0
for (( i=0 ; i < 10; i++ )) ; do echo $i ; done for (( i=0, j=0 ; i+j < 10 ; i++, j++ )) ; do echo $i ; done for fp in $(seq 1.0 .01 1.1) ; do echo $fp ; done
while (( COUNT < MAX )) do ... let COUNT++ done
until test_commands; do commands; done
case $FN in *.gif) gif2png $FN ;; *.jpg) jpg2gif $FN ;; *) print "Format pliku %s nie jest obsługiwany" $FN ;; esac
Instrukcje break
i continue
pozwalają kontrolować przebieg wykonania pętli
Funkcje
function usage() { ... } >&2 function usage { ... } usage() { local HIDN HIDN = 5 ... }
- Nie ma parametrów formalnych; w treści funkcji $1, $2, … przechowują wartości kolejnych parametrów funkcji
- Jedyny sposób na zwrócenie sensownej wartości przez funkcję to przypisanie na zmienną globalną albo wypisanie na STDOUT (wynik funkcji można wtedy złapać w odwrotne ciapy)
- Można używać rekurencji
FUNCNAME
- ta zmienna przechowuje nazwę aktualnie wykonywanej funkcji (
$FUNCNAME
===$FUNCNAME[0]
,$FUNCNAME[1]
zawiera kolejną nazwę funkcji na stosie) caller 0
- w treści funkcji wyświetla zawartość pierwszej ramki stosu (nazwa pliku, numer wiersza, nazwa funkcji)
Sygnały
trap 'echo "Nie pokonasz mnie!"' ABRT EXIT HUP INT TERM QUIT
- przechwytywanie sygnałów (
trap -l
pokazuje listę sygnałów) trap - INT QUIT
- przywrócenie domyślnej obsługi sygnału
- Kod zwracany po zakończeniu skryptu w wyniku otrzymania sygnału ma wartość 128+numer_sygnału.
- Bash deklaruje kilka przydatnych pseudosygnałów. Przed każdym poleceniem rzucany jest sygnał
DEBUG
, sygnałRETURN
jest generowany w chwili wznowienia wykonywania skryptu po wywołaniu funkcji, natomiastERR
jest przesyłany po błędnym zakończeniu pojedynczego polecenia. PseudosygnałERR
nie jest generowany gdy jakieś polecenie shella zakończy się z błędem ale jest np. warunkiem obliczanym w instrukcjiif
Konfiguracja
Pliki startowe
/etc/profile
- ogólnosystemowy, wykonywany jako pierwszy skrypt startowy przy każdym uruchomieniu powłoki
~/.bashrc
- dla interaktywnych powłok Bash
~/.bash_profile
- dla powłok logowania
~/.bash_logout
- wykonywany w chwili wylogowywania
Ciekawe zmienne środowiskowe
LINENO
- liczba wykonanych przez powłokę poleceń
PROMPT_COMMAND
- polecenie wykonywane przed każdorazowym wyświetleniem prompta
RANDOM
- losowa liczba całkowita (kolejne sięgnięcie do tej zmiennej zwraca inną liczbę)
export LESS="--LONG-PROMPT --LINE-NUMBERS --QUIET"
- domyślne parametry dla
less
, m.in. numerowanie wierszy w wyświetlanym pliku TMOUT
- jeśli użytkownik pracujący w trybie interaktywnym nie wprowadzi żadnego polecenia w czasie
$TMOUT
sekund, powłoka zakończy działanie SECONDS
- liczba sekund które upłynęły od czasu uruchomienia powłoki
BASH_LINENO
,FUNCNAME
,BASH_SOURCE
- zmienne tablicowe przechowujące stos (odpowiednio numery wierszy, nazwy procedur, nazwy plików źródłowych)
PIPESTATUS
- zmienna tablicowa zawierająca lista kodów wyjściowych poszczególnych procesów ostatniego potoku (pojedyncze polecenie też jest potokiem)
Prompty
export PS1='u@h A:w $ '
- Nazwa użytkownika @ nazwa systemu, czas oraz ścieżka do bieżącego katalogu
export PS1='[e[0;31m]u@h A:w $[e[m] '
- jw. ale na czerwono żeby wyraźnie odróżniać wyniki różnych poleceń
export PS1='n[u@h:Tl:L$SHLVL:C!:D{%Y-%m-%d_%H:%M:%S_%Z}]n$PWD$ '
- Nazwa użytkownika @ nazwa systemu, nazwa terminala (T), poziom powłoki (L), numer polecenia (C) oraz data i czas w formacie ISO 8601
readline
Biblioteka GNU Readline leży u podłoża Basha i zajmuje się przetwarzaniem danych wejściowych. Zmieniając ustawienia biblioteki, możemy np. zmieniać mechanizm uzupełniania poleceń
~/.inputrc
- plik konfiguracji readline
Przykładowy plik konfiguracyjny z ciekawymi ustawieniami:
# Aby ponownie odczytać plik (i uaktywnić zmiany), należy użyć instrukcji # bind -f $SETTINGS/inputrc # Uwzględnienie systemowych dyrektyw odwzorowania i instrukcji przypisania wartości zmiennym, które są # zapisane w pliku /etc/inputrc $include /etc/inputrc $if Bash # Zignorowania informacji o wielkości liter podczas uzupełniania polecenia set completion-ignore-case on # Dołączenie znaku ukośnika do nazw katalogów (podczas uzupełniania nazwy) set mark-directories on # Wykorzystanie podczas uzupełniania polecenia instrukcji ls -F set visible-stats on # Cykliczna zmiana niejednoznacznych nazw zamiast wyświetlania listy "C-i": menu-complete # Włączenie słyszalnego dzwonka set bell-style audible # Makra użyteczne podczas pracy z powłoką # edycja zmiennej $PATH "C-xp": "PATH=${PATH}eC-eC-aefC-f" # przygotowanie do wpisania słowa otoczonego znakami cudzysłowu -- wstawienie # początkowego i końcowego znaku cudzysłowu i przesunięcie kursora za cudzysłów otwierający "C-x"": """C-b" # wstawienie znaku odwrotnego ukośnika (testowanie symboli specjalnych w sekwencjach znaków i makrach) "C-x\": "\" # Otoczenie znakami cudzysłowu bieżacego lub poprzednioego słowa "C-xq": "eb"ef"" $endif
shopt
shopt -s dirspell
- tabulacja przy wprowadzaniu ścieżki do katalogu próbuje poprawiać pisownię katalogu jeśli użytkownik zrobił literówkę
shopt -q -s cdspell
- automatyczna korekta prostych błędów w użyciu polecenia
cd
shopt -s nocaseglob
- podczas podmiany wartości ścieżek dostępu ignorowana jest wielkość liter
shopt -s globstar
- od tej pory
**
oznacza pełną listę plików i ścieżek poniżej bieżącego katalogu (począwszy od Bash 4)
set
$-
- zmienna przechowująca bieżące ustawienia
set
set -e
- kończy pracę powłoki po zwróceniu przez jakiekolwiek zwykłe polecenie niezerowego kodu zakończenia
set -o vi
- edycja poleceń w trybie Vi (zamiast domyślnego trybu Emacs)
set +h
- powoduje że polecenia shella nie będą haszowane
set -u
- powoduje traktowanie odwołań do nieistniejących zmiennych jako błąd
set -v
- powoduje wypisywanie poleceń na stdout w miarę ich wykonywania
Inne
- Polecana technika to utworzenie katalogu
~/bin
, dodanie tego katalogu do zmiennej$PATH
(na końcu!) i umieszczanie w tym katalogu wszystkich skryptów tworzonych przez użytkownika. Dzięki temu można ich używać tak jakby znajdowały się w/usr/bin
. - Bash pozwala dynamicznie ładować polecenia napisane w języku C (moduły) tak aby nie uruchamiały one osobnych procesów, tzn. będą one działać na zasadzie poleceń wbudowanych w powłokę.
complete -A file -X '!*.@(Z|gz|tgz)' gunzip
- powoduje że dla polecenia
gunzip
klawiszTAB
będzie podpowiadał tylko pliki archiwów echo {05..15}
- wyświetla ciąg liczb 05 06 07 … 15 (począwszy od Bash 4 jednocyfrowe liczby w wynikach tego polecenia będą poprzedzone zerem).
Zadania administracyjne
screen
- Patrz osobny artykuł: Screen
script plik
- od tej pory wszystkie polecenia i ich wyniki będą dodatkowo zapisywane w pliku
plik
, aż do wykonania poleceniaexit
Bezpieczeństwo
unalias -a
- usuwa wszystkie aliasy (nawet jeśli jakiś chitrusek zrobił alias dla polecenia
unalias
) hash -r
- usuwa wszystkie wpisy w tablicy odwzorowań plików wykonywalnych (aby przyspieszyć kolejne wywołania poleceń, powłoka zapamiętuje położenia plików wykonywalnych najczęściej wykonywanych instrukcji; jeden ze sposobów oszukania użytkowników polega na zatruciu tablicy)
ulimit -H -c 0 --
- uniemożliwia tworzenie plików core’a (w których mogą być np. hasła)
Często popełniane błędy
stty
/reset
/tset
- przywraca poprawne ustawienia terminala (po np. próbie wyświetlenia pliku binarnego);
reset
itset
mogą być zbyt drastyczne, zwyklestty
działa poprawnie
- Wyrażenia regularne są wykorzystywane w powłoce bash tylko wraz z operatorem =~
- W skryptach nie można stosować znaków końca wiersza Windows (
dos2unix
) - Nie nazywaj skryptu „
test
„, bo to jest polecenie wbudowane shella (ale np. wywołanie./test
jest OK). - Warto otaczać cudzysłowami wartości przypisywane zmiennym powłoki (na wypadek spacji)
ZMIENNA=misio pysio
- przypisuje zmiennej wartość
misio
i wykonuje poleceniepysio
(w następnym wierszuZMIENNA
nie będzie już istnieć) ZMIENNA="misio pysio"
- nadaje zmiennej wartość
"misio pysio"
Przenośność skryptów
#!/usr/bin/env bash
- bardziej przenośne niż
#!/bin/bash
bash --posix
- wymusza tryb działania zgodny ze standardem POSIX
command -p program parametry
- odpowiada za wyszukanie programu zgodnie z zaleceniami POSIX (np. w Solarisie uwzględnione zostaną katalogi
/usr/xpg4
i/usr/xpg6
)
- Aby skrypt był bardziej przenośny, nie należy używać długich nazw opcji (np.
--field-separator
, które są charakterystyczne dla oprogramowania GNU). - Korzystając z maszyn wirtualnych (np. VMWare) można szybko uzyskać środowisko Solarisa czy BSD żeby w nich przetestować działanie pisanych skryptów
Różnice między Bashem a Sh
Ze względu na przenośność, przy pisaniu skryptów warto obstawać przy standardzie jakim jest przodek Basha, czyli shell sh
. Warto więc wiedzieć jakich konstrukcji nie ma w sh
:
- zmienne tablicowe
- konstrukcje
pushd
,popd
,dirs
,builtin
,command
,printf
,shopt
,local
,select
,time
,((
,[[
- rozwijanie tyldy
- aliasy
- zaawansowane przetwarzanie wartości zmiennych (np.
${#ZMIENNA}
do zwracania długości zmiennej) - konstrukcja
$(...)
(zamiast tego trzeba używać odwrotnych ciapów) - podstawianie procesu
<(list)
- operator przekierowania
&>
Inne
- Programy typu
kdialog
pozwalają na interakcję z użytkownikiem za pomocą prostych okienek GUI (np. wybór pliku, pytanie z odpowiedzią tak/nie, prośba o podanie łańcucha, komunikat itp.);kdialog
jest dostępny razem z KDE,dialog
wykorzystuje bibliotekę znakową NCurses, oprócz tego mamy teżgtkdialog
(pozwala zdefiniować wygląd okienka w XMLu, wykorzystuje GTK+),Xdialog
,zenity
,whiptail
ixmessage
.
kdialog --msgbox "Message goes here."
- Aby sprawdzić czy powłoka działa w trybie interaktywnym, można sprawdzić stan zmiennej środowiskowej
PS1
(istnieje tylko w trybie interaktywnym) lub zmiennej$-
(w trybie interaktywnym ma wartośći
. - Jeśli Bash nie umie znaleźć funkcji/polecenia o danej nazwie, wówczas usiłuje wywołać funkcję
command_not_found_handle
która – jeśli istnieje – wykonuje się jak brakujące polecenie (z parametrów funkcji można odczytać nazwę oryginalnego polecenia i jego parametry) - Programy wiersza poleceń w UNIXie na ogół przestrzegają tradycji która mówi że uruchomienie programu bez opcji powinno być niedestrukcyjne, a jedynie informacyjne. Dzięki temu można bez obaw uruchomić polecenie żeby się zorientować do czego służy
- Ściągnięcie strony WWW za pomocą shella (nie zadziała w Debianie, który ma inaczej skompilowanego Basha):
exec 3 /dev/tcp/www.ippages.com/80 echo -e "GET /simple/?se=1 HTTP/1.0n" >&3 cat <&3
- Kiedy w poleceniu pojawia się symbol
!$
, powłoka zastępuje go ostatnim członem poprzedniego polecenia.
chsh /bin/bash
- powoduje że domyślną powłoką na bieżącym koncie UNIXowym będzie Bash; lista dopuszczalnych powłok jest podana w pliku
/etc/shells
getopts
- polecenie wbudowane shella do użycia przez skrypty do parsowania parametrów wywołania skryptu
mkdir -p ~/misio/pysio/{old,new,dist,bugs}
- tworzy od razu wiele katalogów, opcja
-p
powoduje tworzenie katalogówmisio
ipysio
jeśli jeszcze nie istnieją getconf -a
- wyświetla wartości różnych ograniczeń, np. max. długość polecenia w wierszu wprowadzania (
ARG_MAX
), max. długość loginu (LOGIN_NAME_MAX
), itp. find katalog -name '*z*' -print0 | xargs -0 program
- rozwiązanie problemu ograniczenia długości wiersza wprowadzania; poszczególne argumenty będą rozdzielone znakiem NULL (nie może występować w nazwie pliku), polecenie
program
będzie wykonane raz lub więcej razy w zależności od ilości parametrów wygenerowanych przezfind
logger -p local0.notice "moj komunikat"
- pozwala zalogować komunikat do logu systemowego
nc
- program NetCat pozwala logować komunikaty przez sieć
(cat tresc_wiadomosci; uuencode /plik_zalacznika nazwa_zalacznika) | mail -s "Temat" odbiorca1@host.pl odbiorca2@host.pl
- wysyła maila z treścią i załącznikiem (działanie zależne dość mocno od konfiguracji)
date -d '+4 days' '+%a %Y-%m-%d %H:%M:%S %z'
- wyświetla wskazaną datę w podanym formacie
nohup skrypt &
- demonizowanie skryptu tak aby działał po wylogowaniu się użytkownika (patrz też
screen
) source skrypt
- wykonuje w tej samej powłoce polecenia zawarte we wskazanym skrypcie (zwykłe wywołanie skryptu uruchomiłoby go w podpowłoce)
time polecenie
- wykonuje polecenie i dodatkowo wypisuje informacje o czasie jego wykonania
ulimit
- pozwala odczytywać i ustawiać ograniczenia dla zasobów dostępnych dla procesów uruchamianych z Basha (np. max. rozmiar stosu, max. ilość czasu procesora, wątków, otwartych plików itp.); twardy limit po ustawieniu może być modyfikowany wyłącznie przez administratora; limit miękki może być co najwyżej tak wysoki jak twardy limit
piątek 9. Wrzesień 2011 o 8:41 am
Świetny text , tego szukałem od dawna .. super wszystko zebrane w fajnej pigule ..
piątek 1. Marzec 2013 o 11:19 am
Przy tablicach asocjacyjnych warto by było dodać o wcześniejszym użyciu polecenia: declare -A nazwa_tablicy. Bez tego:
$ echo ${panstwa[pl]}
Wielka Brytania