24.04.2015 Views

Programowanie w systemie UNIX

Programowanie w systemie UNIX

Programowanie w systemie UNIX

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Powłoka ­ co to jest<br />

<strong>Programowanie</strong> w języku powłoki<br />

Powłoka (ang. shell) jest programem umożliwiającym pracę z<br />

systemem <strong>UNIX</strong>. Jej nazwa wywodzi się z graficznej prezentacji<br />

systemu, w której jądro i procesy obsługi wejścia i wyjścia są otoczone<br />

właśnie przez powłokę. Jej funkcją jest odseparowanie użytkownika od<br />

bezpośredniego dostępu do jądra systemu i umożliwienie łatwej i<br />

wszechstronnej pracy.<br />

Podstawowym zadaniem powłoki jest przyjmowanie poleceń<br />

użytkownika i uruchamianie stosownych programów. Do dalszych funkcji<br />

powłoki należy konstruowanie parametrów dla poleceń oraz zarządzanie<br />

sposobem wykonywania programów ­ procesów. Następnym, bardziej<br />

skomplikowanym krokiem jest tworzenie funkcji i procedur powłoki<br />

(skryptów) pozwalających na łączenie wielu poleceń w jedno,<br />

umożliwiając pisanie całych programów dla powłoki.<br />

Powłoka jest programem, z którym użytkownik systemu <strong>UNIX</strong> spotyka<br />

się na samym początku. Jej uruchomienie następuje automatycznie,<br />

bezpośrednio po zalogowaniu (zgłoszeniu) użytkownika w <strong>systemie</strong>. Gdy<br />

widzimy na ekranie znak "$", oznacza to, że powłoka jest już<br />

uruchomiona i oczekuje na podawanie poleceń.<br />

System <strong>UNIX</strong> oferuje wiele powłok. W czasie zajęć przede wszystkim<br />

zostanie omówiona powłoka standardowa oznaczana skrótem sh i<br />

zwana "Bourne shell". Inne powłoki zostaną krótko omówione na<br />

zakończenie wykładu.<br />

Polecenia powłoki ­ podstawy<br />

Wydanie jakiegokolwiek polecenia powłoce wiąże się z podaniem<br />

ciągu znaków. Polecenie składa się z następujących elementów:<br />

- <br />

Nazwą polecenia jest nazwa jakiegokolwiek programu, funkcji powłoki<br />

lub funkcji wewnętrznej powłoki. Opcje to najczęściej zestaw<br />

pojedynczych liter określających sposób wykonania programu.<br />

1


Parametry to informacje dla programu (funkcji) co właściwie ma<br />

wykonać.<br />

Przykład:<br />

rm -i ala.txt prog.c<br />

oznacza wywołanie programu o nazwie rm (czyli służącego do<br />

kasowania plików) z opcją i (invoke) (czyli program przed kasowaniem<br />

będzie pytał o każdy plik, czy na pewno skasować) i parametrami ala.txt i<br />

prog.c ­ nazwami plików do skasowania.<br />

Podstawowymi poleceniami są dwa następujące:<br />

: <br />

# komentarz<br />

Pierwsza z nich (dwukropek) to polecenie puste ­ nic nie robi, zwraca<br />

kod błędu 0. Drugie (hash) to komentarz ­ tym się różni od<br />

poprzedniego, że nie zmienia zmiennej $? ­ kodu błędu ostatnio<br />

wykonanego procesu.<br />

Normalnie powłoka postępuje w taki sposób, że po uruchomieniu<br />

programu czeka na zakończenie jego wykonania i dopiero wtedy znów<br />

wyświetla znak zachęty i oczekuje na wprowadzenie następnego<br />

polecenia. Można jednakże uruchomić program "w tle", to znaczy<br />

powłoka nie będzie czekała na zakończenie jego działania, tylko od<br />

razu wyświetli znak zachęty.<br />

Przykład:<br />

$ obliczenia dane.txt &<br />

[2313]<br />

$<br />

Znak & podany na końcu polecenia powoduje jego uruchomienie w tle.<br />

Środowisko powłoki<br />

Powłoka, aby poprawnie pracować, musi mieć określone środowisko.<br />

Składa się ono z podstawowych dwóch elementów:<br />

­ katalogu aktualnego,<br />

­ zmiennych powłoki.<br />

2


Katalog aktualny (inaczej bieżący) to plik, który dla powłoki jest<br />

skorowidzem odniesienia. Po rozpoczęciu pracy najczęściej<br />

skorowidzem bieżącym jest skorowidz macierzysty (ang. home<br />

directory).<br />

Katalog aktualny zmieniamy poleceniem cd, np.<br />

cd /usr/bin.<br />

Zmienne powłoki określają poszczególne elementy środowiska. Część<br />

zmiennych jest predefiniowanych, tzn. mają swoją wartość już przy<br />

rozpoczęciu pracy.<br />

Wartości zmiennych można wykorzystywać w funkcjach i procedurach<br />

powłoki, można tworzyć nowe zmienne, można zmieniać ich wartość.<br />

Zmienne powłoki mogą być lokalne lub globalne.<br />

Utworzenie nowej zmiennej lub zmiana wartości odbywa się<br />

poleceniem:<br />

=<br />

Nazwa Wartość Przykład<br />

HOME skorowidz<br />

/usr/michk<br />

macierzysty<br />

PATH ścieżka poszukiwań /bin:/usr/bin:/usr/michk/bin:.<br />

TERM typ terminala ansi<br />

PS1 pierwszy (główny) $<br />

znak zachęty<br />

PS2 drugi (pomocniczy) ><br />

znak zachęty<br />

LOGNAME nazwa użytkownika michk<br />

TZ= nazwa strefy GMT-1<br />

czasowej<br />

MAIL nazwa pliku ­ /usr/mail/michk<br />

skrzynki pocztowej<br />

Należy bezwzględnie zwrócić uwagę na brak spacji przed i po znaku<br />

równości ­ jeśli byśmy napisali np. coś takiego<br />

3


PATH = /bin:/usr/bin<br />

to powłoka zinterpretuje to jako wywołanie programu o nazwie PATH i<br />

dwóch parametrach: = oraz /bin:/usr/bin.<br />

Przykłady nadawania wartości:<br />

PATH=/bin:/usr/bin<br />

ala=taki_sobie_tekst<br />

piec=5<br />

ala=teraz_inny_tekst<br />

Ale<br />

ala=taki sobie tekst<br />

oznacza tymczasowe nadanie zmiennej ala wartości taki, a następnie<br />

wykonanie programu o nazwie sobie z jednym parametrem ­ tekst. W<br />

ten sposób powłoka umożliwia nadanie zmiennej wartości tylko na czas<br />

wykonania polecenia (w tym przypadku sobie).<br />

cd $HOME<br />

spowoduje powrót do skorowidza macierzystego<br />

Wartości poszczególnych zmiennych możemy obejrzeć poprzez<br />

polecenie echo:<br />

echo $PATH<br />

wyświetli na ekranie wartość zmiennej PATH.<br />

Wartości wszystkich zmiennych od razu wyświetla polecenie set.<br />

Zmienne są wyświetlane w kolejności alfabetycznej.<br />

Często pojawia się problem kolizji nazw zmiennych. Jeśli mamy<br />

zdefiniowaną następującą zmienną:<br />

ala=tekst<br />

to użycie jej w postaci<br />

echo $alaxyz<br />

spowoduje wyświetlenie tekstu:<br />

tekstxyz<br />

Jeśli dodatkowo zdefiniujemy zmienną:<br />

alaxyz=coś_innego<br />

4


to poprzednie polecenie echo oczywiście wyświetli teraz wartość<br />

zmiennej alaxyz:<br />

coś_innego.<br />

Aby uzyskać wartość zmiennej ala w takiej sytuacji stosuje się nawiasy<br />

klamrowe:<br />

echo ${ala}xyz<br />

powoduje wyświetlenie<br />

tekstxyz.<br />

Wykaz zmiennych polecenia powłoki:<br />

Nazwa Wartość<br />

Przykład<br />

$0 nazwa wykonywanego programu sh<br />

$1 pierwszy parametr wywołania ala.txt<br />

$2...$9 następne parametry wywołania prog.c<br />

$* wszystkie parametry wywołania ala.txt prog.c<br />

$@ jw, ale parametry jako osobne "ala.txt"<br />

łańcuchy znaków<br />

"prog.c"<br />

$# liczba parametrów 2<br />

$­ opcje powłoki podane przy wywołaniu -xv<br />

$? kod błędu ostatnio wykonanego 0<br />

polecenia<br />

$$ numer procesu powłoki 12345<br />

$! numer procesu ostatnio wykonanego 12560<br />

w tle<br />

A oto sposób utworzenia pliku tymczasowego o unikalnej nazwie:<br />

/tmp/plik.$$<br />

Przekierowanie wejścia i wyjścia, potoki<br />

Każdemu procesowi na początku jego pracy system udostępnia trzy<br />

strumienie:<br />

­ standardowe wejście ­ strumień o numerze 0,<br />

­ standardowe wyjście ­ strumień o numerze 1,<br />

­ standardowe wyjście błędu ­ strumień o numerze 2.<br />

Powłoka uruchamiając każdy proces udostępnia mu swoje<br />

standardowe strumienie. Ponieważ na początku ich rolę pełni terminal<br />

5


(wejście ­ klawiatura, wyjście ­ ekran), więc i programy ­ procesy<br />

uruchamiane przez użytkownika będą miały tak przyporządkowane<br />

strumienie.<br />

Istnieje możliwość zmiany ustawienia strumieni ­ przekierowanie<br />

(ang. redirection). Wiele programów systemu <strong>UNIX</strong> to tzw. filtry, czyli<br />

czytające tylko ze standardowego wejścia i piszące tylko na<br />

standardowe wyjście. Używając mechanizmu przekierowania można<br />

uzyskać efekt ich pracy na plikach.<br />

Przekierowanie wyjścia może odbywać się dwoma sposobami:<br />

1) polecenie > nazwa_pliku<br />

2) polecenie >> nazwa_pliku<br />

Pierwszy sposób powoduje zapisanie do pliku nazwa_pliku całego<br />

standardowego wyjścia z polecenia. Jeśli taki plik istniał, jego poprzednia<br />

zawartość zostanie usunięta.<br />

Drugi sposób powoduje dopisanie wyjścia standardowego z polecenia<br />

do ew. istniejącej już zawartości pliku.<br />

Przekierowanie wejścia realizujemy następująco:<br />

polecenie < nazwa_pliku<br />

Proces uruchomiony poleceniem będzie odczytywał dane z pliku<br />

nazwa_pliku, a nie z terminala.<br />

Z pojęciem przekierowania łączy się też mechanizm następujący:<br />

polecenie


1) unikamy niepotrzebnych komunikatów diagnostycznych w pliku.<br />

Najczęściej jest on wejściem do następnego programu, dla którego<br />

komunikat diagnostyczny jest bezsensowny,<br />

2) uzyskujemy na terminalu informację o błędzie. Jeśli program zauważa<br />

błąd w danych, to wyświetla komunikat; gdyby komunikat też był<br />

przekierowany do pliku, użytkownik w ogóle nie zorientowałby się, że<br />

zdarzyła się błędna sytuacja.<br />

Jeżeli nie chcemy, aby komunikaty o błędach pojawiały się na<br />

ekranie, to możemy niezależnie przekierować standardowe wyjście<br />

błędów. Odbywa się to w sposób:<br />

polecenie 2> nazwa_pliku<br />

Można też połączyć kilka strumieni w jeden, podając np. że wyjście ze<br />

strumienia 5 ma być połączone z wyjściem strumienia 1 (standardowego<br />

wyjścia):<br />

polecenie 5>&1<br />

Przekierowania są ważnym elementem w przypadku wykonywania<br />

programów w tle. Standardowym wejściem takiego programu jest /dev/<br />

null, czyli wejście puste, zaś wyjściem jest terminal. Aby uniknąć<br />

pomieszania informacji na ekranie, stosuje się przekierowanie:<br />

program wyniki.txt 2>bledy.txt &<br />

Przykłady:<br />

Typowym poleceniem dla przykładów na przekierowanie jest polecenie<br />

cat:<br />

cat plik_1 plik_2 ... plik_n<br />

Gdy nie podamy żadnych parametrów poleceniu cat, to odczyt<br />

następuje ze standardowego wejścia, więc w takim wypadku cat po<br />

prostu kopiuje standardowe wejście na standardowe wyjście.<br />

cat prog.c >prog1.c<br />

powoduje przekopiowanie zawartości pliku prog.c do pliku prog1.c<br />

7


cat prog1.c<br />

daje efekt identyczny<br />

cat *.txt >wszystkie 2>bledy<br />

kopiuje wszystkie pliki o nazwach kończących się na .txt do pliku<br />

wszystkie, zaś komunikaty o błędach trafiają do pliku bledy.<br />

cat *.txt >/dev/null<br />

Wyobraźmy sobie program o nazwie rozdziel, który odczytuje<br />

standardowe wyjście i w zależności od pierwszego znaku każdego<br />

wiersza, rozdziela te wiersze następująco:<br />

­ małe litery ­ strumień 3<br />

­ duże litery ­ strumień 4<br />

­ cyfry ­ strumień 5<br />

­ inne ­ strumień 6<br />

Dla takiego programu stosujemy polecenie:<br />

rozdziel litery 4>&3 5>cyfry 6>reszta<br />

Polecenie<br />

cat ala.txt<br />

spowoduje wyzerowanie pliku ala.txt! Dlaczego? ćwiczenie<br />

samodzielne.<br />

Bardzo często wyjście jednego polecenia jest wejściem następnego, np.<br />

ls /usr/student >/tmp/mkdir<br />

grep abcd


Ewentualne przeadresowania wejścia i wyjścia odnoszą się tylko do<br />

poszczególnych poleceń, np.<br />

ls /usr/student | grep abcd 2>bledy<br />

powoduje przekierowanie standardowego wyjścia błędu tylko polecenia<br />

grep. Można uzyskać łączne przekierowanie stosując grupowanie<br />

poleceń.<br />

Rozwijanie nazw plików i cytowanie<br />

Można używać następujących metaznaków:<br />

* pasuje do dowolnego tekstu<br />

? pasuje do dowolnego znaku<br />

[...]pasuje do każdego znaku z wymienionych między nawiasami<br />

[x-y]pasuje do każdego znaku znajdującego się pomiędzy x i y (z<br />

nimi włącznie)<br />

[!..]pasuje do każdego znaku z wyjątkiem znaków podanych po<br />

wykrzykniku.<br />

Uwaga: Poszczególne formy [] można łączyć ze sobą, np.[a-zA-<br />

Z0123456789]<br />

9


Wyobraźmy sobie strukturę skorowidzów:<br />

/usr/michk/<br />

ala.txt<br />

info.1<br />

prog.c<br />

obliczenia/<br />

dane1.txt<br />

wyniki.txt<br />

rozne/<br />

rozne.1<br />

rozne.2<br />

rozne.3<br />

Skorowidzem bieżącym jest /usr/michk<br />

Warto zwrócić uwagę, że występująca kropka w nazwach plików nie<br />

rozdziela nazwy od rozszerzenia (jak w DOS­ie), ale jest po prostu<br />

elementem nazwy takim samym, jak każdy inny znak.<br />

Powłoka zawsze dokonuje rozwinięcia w kolejności alfabetycznej.<br />

Metaznak Wynik<br />

*.1 info.1 (ale nie rozne/rozne.1 !)<br />

*/* obliczenia/dane1.txt obliczenia/wyniki.txt<br />

rozne/rozne.1 rozne/rozne.2 rozne/rozne.3<br />

[a-k]*<br />

[!abc]*c<br />

*o*<br />

ala.txt info.1<br />

prog.c obliczenia rozne<br />

info.c obliczenia rozne prog.c<br />

*.? info.1 prog.c<br />

*.?? *.?? (nic nie pasuje)<br />

*.??? ala.txt<br />

*[!.]* obliczenia rozne<br />

10


cat *.?<br />

powoduje, że program cat otrzyma jako pierwszy parametr info.1,<br />

jako drugi prog.c, czyli tak, jakby podać polecenie:<br />

cat info.1 prog.c<br />

Cytowanie znaków (substytucja)<br />

Czasami nie chcemy, aby powłoka rozwijała nazwy plików.<br />

Przykładem może być polecenie find:<br />

find . ­name *.txt ­print<br />

powoduje wyszukanie i wyświetlenie nazw wszystkich plików pasujących<br />

do podanego wzorca ­ w tym przypadku *.txt. Przeszukiwane są<br />

skorowidze ­ bieżący i wszystkie podskorowidze.<br />

Takie podanie polecenia powłoce spowoduje jednak rozwinięcie nazwy<br />

pliku i w rezultacie program find otrzyma następujące parametry:<br />

find . ­name ala.txt –print<br />

co całkowicie zmienia znaczenie ­ teraz znalezione będą tylko pliki o<br />

nazwie ala.txt.<br />

Aby zabronić powłoce dokonywania substytucji, stosowane jest<br />

cytowanie znaków. Są dostępne następujące mechanizmy:<br />

­ poprzedzanie znakiem "\" (backshash). Każdy znak po nim nie jest<br />

interpretowany przez powłokę, a więc można nasze polecenie<br />

podać w sposób następujący:<br />

find . ­name \*.txt –print<br />

tym znakiem możemy podać programowi wszystkie znaki, włącznie z<br />

takimi, które są interpretowane przez powłokę:<br />

program dane.tx \&<br />

spowoduje przekazanie znaku "&" do programu, a nie wykonanie<br />

programu w tle.<br />

poprzez ujęcie tekstu w cudzysłowy, np.<br />

11


find . -name "*.txt" -print<br />

takie cytowanie powoduje, że nie jest dokonywane rozwinięcie nazw<br />

plików w tekście w cudzysłowach oraz dodatkowo, cały tekst ujęty w<br />

cudzysłowy jest traktowany jako pojedynczy parametr dla polecenia.<br />

grep "ala ma kota" dane.txt<br />

powoduje wyszukanie tekstu ala ma kota w pliku dane.txt.<br />

$ echo "To jest<br />

> wielowierszowy pojedynczy<br />

> parametr dla polecenia<br />

> echo i tak właśnie będzie wyświetlony"<br />

- poprzez ujęcie tekstu w apostrofy:<br />

find . -name ‘*.txt’ -print<br />

od poprzedniego rozwiązania różni się tym, że nie jest dokonywana<br />

tutaj żadna substytucja, także nazw zmiennych.<br />

Zestaw poleceń<br />

nazwa=\*.txt<br />

echo $nazwa<br />

echo ”$nazwa”<br />

echo ‘$nazwa’<br />

spowoduje wyświetlenie kolejno<br />

prog.txt<br />

*.txt<br />

$nazwa<br />

Substytucja poleceń<br />

Powłoka jest w stanie wykonać dane polecenie i wyniki jego działania<br />

przedstawić jako listę parametrów dla innego polecenia. Odbywa się to<br />

przez umieszczenie jej wywołania w znakach akcentu, np.:<br />

rm -i `find . -name *.tmp -print`<br />

12


Najpierw wykonywane jest polecenie find, podające listę nazw plików<br />

odpowiadających wzorcowi, np.:<br />

./dane.tmp<br />

./info.tmp<br />

./obliczenia/aa.tmp<br />

./obliczenia/bb.tmp<br />

./obliczenia/cc.tmp<br />

Ten wykaz zastępuje polecenie find podane w znakach akcentu i<br />

dopiero teraz powłoka wykonuje polecenie rm:<br />

rm -i ./dane.tmp ./info.tmp ./obliczenia/aa.tmp<br />

./obliczenia/bb.tmp ./obliczenia/cc.tmp<br />

Ten mechanizm jest źródłem dużych możliwości w programowaniu<br />

powłoki.<br />

Grupowanie poleceń<br />

Polecenia powłoki mogą być zbierane w grupy dwojakiego rodzaju:<br />

­ poprzez ujęcie listy poleceń w nawiasy klamrowe {}<br />

­ poprzez ujęcie listy poleceń w nawiasy ()<br />

Polecenia w liście rozdzielamy średnikami lub znakami nowej linii; w<br />

przypadku nawiasów klamrowych należy podać też średnik po ostatniej<br />

poleceniu.<br />

Ujęcie listy poleceń w nawiasy klamrowe służyć może wspólnemu<br />

przekierowaniu wejścia / wyjścia, np.<br />

{ ls /usr/michk | grep abcd ; } 2>bledy<br />

{ cat naglowek.txt; ls -l | grep abcd ; } >info.1<br />

Inne zastosowania grupowania w nawiasy klamrowe to wszystkie<br />

takie sytuacje, w których powłoka wymaga jednego polecenia, a<br />

potrzeba wykonać kilka.<br />

13


Ujęcie poleceń w nawiasy powoduje uruchomienie nowej powłoki<br />

(mówimy: podpowłoki) i wykonanie poleceń przez tę podpowłokę. Taki<br />

mechanizm stosuje się, gdy użytkownik nie chce zmieniać środowiska<br />

powłoki.<br />

Ponieważ np. skorowidz bieżący należy do środowiska, polecenia:<br />

cd / ; ls -l<br />

spowodują wyświetlenie zawartości skorowidza głównego; po czym<br />

bieżącym skorowidzem pozostanie nadal skorowidz główny. Użycie<br />

nawiasów:<br />

( cd / ; ls -l )<br />

powoduje taki sam efekt, ale po zakończeniu działania tych poleceń<br />

skorowidz bieżący pozostanie bez zmian, gdyż zmienił się tylko w<br />

podpowłoce, która już zakończyła działanie.<br />

Innym zastosowaniem nawiasów może być wykonanie ciągu poleceń<br />

w tle, przy czym wszystkie nie wykonują się niezależnie, ale jedno po<br />

drugim:<br />

( cd obliczenia ; oblicz wyniki.txt<br />

write $LOGNAME "koniec obliczeń") &<br />

Wykonanie względne || i &&<br />

Wykonanie jednego polecenia można uzależnić od efektów działania<br />

innego polecenia. Temu służą dwa operatory: || oraz &&.<br />

Operator || łączący dwa polecenia oznacza, że drugie z nich będzie<br />

wykonane tylko wtedy, gdy wykonanie pierwszego zakończy się błędem.<br />

Operator && działa przeciwnie ­ drugie polecenie wykonuje się, gdy<br />

pierwsze nie kończy się błędem.<br />

Kod błędu ostatnio wykonanego programu możemy zawsze badać<br />

analizując zmienną powłoki $?; innym sposobem jest opisywana właśnie<br />

konstrukcja:<br />

14


grep abcd >wynik.txtwynik.txt


export zmiennanadaje globalny zasięg zmiennej. Taka zmienna jest<br />

dziedziczona przez podpowłoki i inne procesy<br />

potomne. Samo słowo export, bez parametrów<br />

wyświetla wykaz zmiennych eksportowanych przez<br />

powłokę.<br />

read zmienna<br />

return n<br />

set<br />

set -fntvx<br />

odczytanie jednego wiersza z terminala i wpisanie go<br />

jako wartości podanej zmiennej (tu zmienną jest<br />

łańcuch znaków). To polecenie umożliwia pisanie<br />

interakcyjnych skryptów i funkcji.<br />

zakończenie działania funkcji powłoki. Parametr<br />

podaje kod błędu, domyślnie 0.<br />

wyświetla zmienne powłoki.<br />

ustawia opcje powłoki (można to robić też przy<br />

wywołaniu powłoki, patrz dalszy rozdział.<br />

set parametry...ustawia parametry powłoki, dostępne przez $1, $2<br />

itd.<br />

shift n przesunięcie parametrów. Parametr drugi staje się $1,<br />

trzeci $2 itd. Parametr pierwszy jest tracony. Polecenie<br />

użyteczne, gdy parametrów jest więcej niż dziewięć.<br />

Można ew. przesunąć o więcej niż 1, podając<br />

stosowne n.<br />

trap<br />

ustawianie odpowiedzi powłoki na sygnały.<br />

type nazwa... podaje, jak dana nazwa (nazwy) byłaby<br />

zinterpretowana jako polecenie (wewnętrzna, funkcja,<br />

skrypt, program...)<br />

16


Instrukcje strukturalne (if, case, for, while, until)<br />

Jak wspomniano na wstępie, powłoka oferuje mechanizmy budowy<br />

funkcji i procedur w celu programowania powłoki. W takim przypadku<br />

nieodzowne stają się instrukcje sterujące przepływem programu,<br />

ustalające kolejność wykonywanych działań. Powłoka posiada takie<br />

mechanizmy.<br />

Instrukcja if<br />

Syntaktyka:<br />

if <br />

then<br />

else<br />

fi<br />

Powłoka wykonuje polecenie. Jeśli kod błędu wynosi 0, to<br />

wykonywana jest lista_poleceń_1; w przeciwnym wypadku<br />

lista_poleceń_2. Część else jest opcjonalna i nie musi występować.<br />

Przykład:<br />

if test -f temp.txt<br />

then rm temp.txt<br />

fi<br />

Uwaga: Wszystkie te polecenia można zapisać w jednym wierszu,<br />

rozdzielając średnikami kolejne polecenia:<br />

if test -f temp.txt; then rm temp.txt; fi<br />

Średniki są tu niezbędne; inaczej powłoka nie wiedziałaby, gdzie kończy<br />

się jedno polecenie i zaczyna drugie.<br />

W przypadku wykonywania zagnieżdżonych instrukcji if:<br />

if <br />

then<br />

elseif <br />

then <br />

else if <br />

then <br />

else <br />

fi<br />

fi<br />

fi<br />

17


można używać konstrukcji łączącej else if w jedno elif:<br />

if <br />

then <br />

elif <br />

then <br />

elif <br />

then <br />

else <br />

fi<br />

Można teraz wrócić do poprzedniego rozdziału, z operatorami || i &&. Jak<br />

widać oba zapisy są równoważne:<br />

polecenie_1 && polecenie_2 if <br />

then <br />

fi<br />

polecenie_1 || polecenie_2 if <br />

then<br />

else <br />

fi<br />

Instrukcja case.<br />

Syntaktyka:<br />

case in<br />

) ;;<br />

...<br />

) ;;<br />

esac<br />

W przypadku wykonywania tej samej listy poleceń dla kilku wzorów,<br />

można podać:<br />

||...| ) ;;<br />

Łańcuch jest porównywany po kolei z podanymi wzorami. W<br />

przypadku znalezienia zgodności, wykonywana jest odpowiednia lista<br />

poleceń. Zgodność jest rozumiana identycznie jak przy rozwijaniu nazw<br />

plików z użyciem metaznaków, więc aby uzyskać wykonanie listy<br />

18


"otherwise" (gdy żaden wzór nie pasuje), należy na końcu podać wzór w<br />

postaci gwiazdki, jak w przykładzie.<br />

Przykład:<br />

# skrypt o nazwie append<br />

case $# in<br />

1)cat >> $1 ;;<br />

2)cat >$2 ;;<br />

*)echo 'składnia: append [z] do' ;;<br />

esac<br />

Uwaga: Po wykonaniu stosownej listy poleceń nie są wykonywane<br />

kolejne listy, jak to ma miejsce w języku C ­ powłoka zachowuje się<br />

podobnie do języka Pascal.<br />

Instrukcja for.<br />

Składnia:<br />

for <br />

do<br />

<br />

done<br />

for in <br />

do<br />

<br />

done<br />

Pierwsza z tych form powoduje, że lista poleceń zostanie wykonana tyle<br />

razy, ile parametrów przekazano do powłoki lub skryptu. Zmienna po<br />

podanej nazwie nazwa będzie przyjmowała po kolei wartości tych<br />

parametrów.<br />

Przykład:<br />

for i<br />

do<br />

echo $i<br />

done<br />

wyświetli wykaz wszystkich parametrów, każdy w osobnym wierszu.<br />

19


Druga forma powoduje wykonanie listy poleceń dla każdego słowa w<br />

podanej liście słów. Typowym przykładem jest wykonanie jakiejś akcji dla<br />

podanych plików:<br />

for i in *.txt<br />

do<br />

if grep „Plik do skasowania”


Instrukcja while.<br />

Syntaktyka:<br />

while <br />

do <br />

done<br />

Wykonanie tej instrukcji polega na wielokrotnym wykonywaniu<br />

pierwszej listy poleceń; w przypadku, gdy kod błędu ostatniego z poleceń<br />

w liście wynosi 0, wykonywana jest druga lista poleceń i proces się<br />

powtarza; kod błędu niezerowy oznacza zakończenie tej pętli.<br />

Przykład:<br />

while<br />

echo -n "Czy wykonać (t/n) "<br />

read x<br />

case $ x in<br />

[tTnN]* ) false ;;<br />

* ) true ;;<br />

esac<br />

do<br />

echo Podaj "t" lub "n"<br />

done<br />

Instrukcja until.<br />

Syntaktyka:<br />

until <br />

do <br />

done<br />

Wykonanie tej instrukcji polega na wielokrotnym wykonywaniu<br />

pierwszej listy poleceń; w przypadku, gdy kod błędu ostatniego z poleceń<br />

w liście jest niezerowy, wykonywana jest druga lista poleceń i proces się<br />

powtarza; zerowy kod błędu oznacza zakończenie tej pętli.<br />

21


Funkcje powłoki<br />

Powłoka umożliwia definicje funkcji. Funkcje te mogą być później<br />

wywoływane. Definicja funkcji wygląda następująco:<br />

nazwa() polecenie<br />

W ten sposób tworzymy funkcję o nazwie nazwa i treści polecenie.<br />

Wywołując funkcję możemy podawać parametry:<br />

komunikat() { echo błędn$1 $2 w $3 ; }<br />

komunikat y znak pliku błędny znak w pliku<br />

komunikat a linia danych błędna linia w danych<br />

Przykład:<br />

gettn() {<br />

while<br />

echo -n $*<br />

echo -n " (t/n) ? "<br />

do<br />

read yn reszta<br />

case $yn in<br />

[yY] ) return 0 ;;<br />

[nN] ) return 1 ;;<br />

* ) echo "Proszę podać T lub N" >&2 ;;<br />

esac<br />

done ;<br />

}<br />

Wykorzystanie:<br />

gettn "Czy skasować plik" || break ;<br />

Inny przykład:<br />

ccd () { cd $1 ; PS1="`pwd` $" ;}<br />

Powoduje wyświetlanie bieżącego skorowidza jako znaku zachęty<br />

powłoki. Każdorazowe wykonywanie ccd zamiast cd umożliwia bieżące<br />

zmiany znaku zachęty:<br />

$ ccd /usr/bin<br />

/usr/bin $<br />

22


Procedury powłoki, podpowłoka<br />

Procedury powłoki (skrypty) to zapisane w oddzielnych plikach<br />

polecenia powłoki. Wykonujemy je podając polecenie<br />

sh nazwa_pliku<br />

lub krócej<br />

nazwa_pliku<br />

gdy plik ma ustawiony atrybut wykonywalności x.<br />

Takie wywołanie powoduje uruchomienie nowej powłoki (podpowłoki),<br />

która wykonuje polecenia zapisane w skrypcie. Podpowłoka dziedziczy<br />

środowisko, a więc skorowidz bieżący i wszystkie zmienne globalne<br />

powłoki.<br />

expr program obliczający wyrażenia arytmetyczne. Można go też<br />

wywołać nazwą "[" i wtedy na zakończenie wyrażenia też trzeba<br />

podać znak "]":<br />

expr 10 + 5<br />

[ 11 \* 20 ]<br />

a=1<br />

a=`expr $a + 1`<br />

test program badający różne warunki logiczne, np.<br />

test -f plik czy plik istnieje<br />

test -d plik czy skorowidz istnieje<br />

test $a -gt 10 czy zmienna a zawiera liczbę większą<br />

od 10<br />

test -r plik -a $a eq 10 czy wolno czytać plik i czy<br />

zmienna a jest równa 10<br />

grep program wyszukujący teksty w pliku<br />

grep abcd *.c szukanie tekstu abcd w plikach *.c<br />

sed program do edycji; w skryptach wykorzystywany do zamiany w<br />

plikach jednych tekstów na inne<br />

23


Przykład skryptu:<br />

# listdir - skrypt do wyświetlania drzewa<br />

# skorowidzów - zagłębionych.<br />

# wywołanie: listdir <br />

#<br />

#skrypt wywołuje się rekurencyjnie - wtedy jako drugi<br />

#parametr przekazywany jest zestaw spacji będący<br />

# wcięciem przy rysowaniu drzewa<br />

odstep=""<br />

# zmienna odstęp określa zagłębienie wcięć w<br />

rysowaniu drzewa<br />

cd $1<br />

case $# in<br />

2) odstep="$2" ;;<br />

esac<br />

# najpierw wyświetlamy zwykłe pliki<br />

for i<br />

do<br />

if test ! -d $i<br />

then<br />

echo $odstep $i<br />

if<br />

done<br />

# teraz zajmujemy się skorowidzami<br />

for i<br />

do<br />

if test -d $i<br />

then<br />

echo $odstep $i "/"<br />

listdir $i "$odstep "<br />

fi<br />

done<br />

W skryptach często dochodzi do sytuacji, w której trzeba podać<br />

danemu programowi z góry określone dane, np. trzeba utworzyć plik z<br />

określoną zawartością. Oczywiście możemy utworzyć wcześniej wzorzec<br />

24


(szablon) takiego pliku, a następnie korzystając z przekierowania<br />

utworzyć nam potrzebny:<br />

cat plik<br />

Istnieje jednakże sposób umożliwiający takie działanie bez tworzenia<br />

dodatkowych plików. Jest to tzw. mechanizm dokumentu włączonego<br />

(ang. here document). W skrypcie podajemy następujące polecenia:<br />

cat >plik


Opcje wykonania powłoki<br />

Podczas uruchamiania powłoki oraz w trakcie jej działania możemy<br />

podawać opcje. Uruchamiając podajemy je jak każdemu programowi, np:<br />

sh -xv<br />

W trakcie działania powłoki poleceniem wbudowanym set:<br />

set -xv<br />

Aby opcję wyłączyć, należy podać po niej znak +:<br />

set -x+<br />

Powłoka ma następujące opcje:<br />

­c tekst powoduje wykonanie pojedynczego polecenia, podanego za<br />

opcją. Nie można jej ustawić poleceniem set.<br />

­r wywołanie powłoki okrojonej<br />

­s polecenia są czytane z wejścia standardowego<br />

­e zakończenie powłoki, jeśli wystąpi błąd przy wykonaniu polecenia<br />

­f zablokowanie rozwijania nazw plików<br />

­n polecenia są tylko czytane, nie są wykonywane. Służy do<br />

uruchamiania skryptów<br />

­u traktowanie jako błędu użycia niezdefiniowanej zmiennej. Normalnie<br />

wstawiany jest łańcuch pusty<br />

­v wyświetlanie wierszy poleceń po ich przeczytaniu<br />

­x wyświetlenie wierszy poleceń przed wykonaniem (opcje ­xv<br />

umożliwiają obejrzenie, jak działa substytucja)<br />

­­ znak ­ jest argumentem, nie opcją.<br />

26


Pliki inicjacyjne<br />

Na początku pracy z powłoką należy wykonać kilka poleceń,<br />

powtarzanych z sesji na sesję. Dlatego w skorowidzu macierzystym<br />

użytkownika istnieje plik o nazwie .profile, zawierający polecenia dla<br />

powłoki do wykonania. Polecenia wykonują się tylko dla pierwszej,<br />

głównej powłoki ­ wywoływanie następnych podpowłok nie powoduje<br />

wykonania się tych poleceń.<br />

W pliku .profile (można go uznać za odpowiednik pliku<br />

AUTOEXEC.BAT w DOS­ie) znajdują się np. polecenia ustawiające<br />

zmienną PATH:<br />

PATH=$PATH:$HOME/bin<br />

Ponieważ każda inna powłoka (csh, ksh itd) ma inną syntaktykę,<br />

każda z nich ma inne pliki inicjacyjne, np. dla powłoki bash wykonuje się<br />

plik o nazwie .bash_profile.<br />

Inne powłoki ­ csh, ksh, tcsh, bash<br />

Powłoka sh jest standardową powłoką systemu <strong>UNIX</strong>, do dyspozycji<br />

użytkownika są jeszcze następujące powłoki:<br />

csh (C Shell) powłoka o syntaktyce poleceń zbliżonej do języka C<br />

(chodzi przede wszystkim o instrukcje strukturalne)<br />

ksh (Korn Shell) niezależnie powstała powłoka podobna do sh, lepsza<br />

od niej pod kilkoma względami<br />

tcsh ulepszona wersja csh<br />

bash (Bourne Again Shell) ­ ulepszona powłoka sh.<br />

27


Ćwiczenia<br />

1. Opracować skrypt generujący plik .profile i wpisuje go do skorowidza<br />

podanego użytkownika. Plik .profile ma wyświetlać tekst powitania,<br />

ustawiać zmienne powłoki, inicjować inne zmienne, wyświetlać datę i<br />

czas itp.<br />

2. Opracować skrypt wyświetlający drzewo systemu plików począwszy<br />

od podanego skorowidza, z odpowiednimi odstępami od początku linii.<br />

Uwaga: Selekcja plików może obejmować dodatkowy warunek<br />

(nazwa, data ostatniej modyfikacji, atrybuty, typ pliku).<br />

Utrudnienie: wyświetlanie wcięć razem ze znakami semigraficznymi<br />

ilustrującymi strukturę drzewa (jak Xtree).<br />

3. Opracować skrypt podający wszystkie pliki z określonego skorowidza,<br />

do których dany użytkownik posiada podane parametrem prawa<br />

dostępu.<br />

4. Opracować skrypt umożliwiający konwersacyjne wmontowywanie i<br />

wymontowywanie systemów plików, jak również sprawdzanie<br />

zajętości urządzeń dyskowych.<br />

5. Opracować skrypt dokonujący statystyki wybranych gałęzi systemu<br />

plików (ile plików, ile podskorowidzów, jakie uprawnienia dostępu<br />

użytkownika wywołującego skrypt, ilu plików właścicielami są: root,<br />

bin).<br />

6. Opracować skrypt wyświetlający z wybranych gałęzi systemu plików<br />

nazwy plików o podanych uprawnieniach dostępu.<br />

28

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!