Programowanie w systemie UNIX
Programowanie w systemie UNIX
Programowanie w systemie UNIX
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 DOSie), 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 DOSie) 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