Interfejs uzytkownika - interpreter poleceń

ŁF

LINUX - Interfejs użytkownika.

4. INTERPRETER POLECEŃ

</span>

Działanie interpretera poleceń

</span>

W systemach UNIX i Linux interpreter poleceń określany jest również jako powłoka (ang. shell). Nazwa wywodzi się stąd, że program ten pełni rolę warstwy pośredniczącej między użytkownikiem a systemem operacyjnym. W dalszej części podręcznika będziemy posługiwać się zamiennie obydwoma określeniami.

(1.1) Przegląd interpreterów

Pierwszym interpreterem napisanym dla systemu UNIX był sh, czyli powłoka Bourne'a (ang. Bourne shell). Program ten odznacza się dużą szybkością działania i z tego względu jest wciąż powszechnie wykorzystywany do uruchamiania skryptów. Jego funkcjonalność jest niestety mocno ograniczona podczas pracy interaktywnej ze względu na brak licznych udogodnień, które oferują nowocześniejsze powłoki.

Znacznie wygodniejszy jest drugi klasyczny interpreter csh (ang. C shell). Program csh oferuje m.in. historię poleceń, aliasy, i sterowanie pracami. Składnia złożonych poleceń jest bardzo zbliżona do języka C (w którym został napisany) i różni się znacząco od składni stosowanej w sh.

Trzecim klasycznym interpreterem jest ksh (ang. Korn shell), stanowiący rozszerzenie programu sh o wiele nowych funkcji. Z założenia, ksh przeznaczony był dla administratorów i raczej nie zdobył uznania zwykłych użytkowników ze względu na skomplikowaną składnię.

Żaden z wymienionych programów nie jest dostępny w klasycznej wersji w systemie Linux.

Obecnie największą popularność cieszą się nowoczesne interpretery łączące duże możliwości z łatwością obsługi. Należy tu wymienić powłoki zsh i bash (ang. Bourne Again shell), powstałe z rozwinięcia sh, oraz powłokę tcsh. Powłoka zsh staje się powoli standardem systemu UNIX, zaś bash jest od samego początku podstawowym i domyślnym interpreterem Linuxa.

W dalszej części tej lekcji opisujemy powłokę bash.

(1.2) PLiki konfiguracyjne

Powłoka bash może wykorzystać kilka plików konfiguracyjnych w zależności od sposobu uruchomienia.

Powłoka uruchomiona po zalogowaniu użytkownika (ang. login shell) odczytuje kolejno zawartość następujących plików:

  • /etc/profile
  • ~/.bash_profile
  • ~/.bash_login
  • ~/.profile


Każda powłoka interaktywna odczytuje zawartość plików:

  • /etc/bashrc
  • ~/.bashrc
(1.3) Edycja poleceń

Powłoka bash daje bogate możliwości edycji poleceń. Pozwala łatwo modyfikować wpisane polecenie poprzez przemieszczanie się kursorami ARROW_L.GIF i ARROW_R.GIF w wierszu, usuwanie niepoprawnych znaków i wstawianie nowych. Jest to szczególnie przydatne do poprawiania długich poleceń złożonych z wielu wyrazów, w których błąd popełniono na samym początku. Opisany poniżej mechanizm historii pozwala przywołać takie polecenie, poprawić i ponownie wykonać.

Interpreter umożliwia ponadto uzupełnianie nazw poleceń i plików podczas edycji wiersza polecenia. Po wprowadzeniu początkowego fragmentu nazwy polecenia można wcisnąć [Tab], aby powłoka odnalazła i uzupełniła nazwę. Poszukiwania prowadzone są wśród wbudowanych poleceń oraz w katalogach wymienionych w ścieżce poszukiwań programów PATH. Podobnie odbywa się uzupełnianie nazw plików z tym, że poszukiwania dotyczą tylko jednego katalogu wskazanego w początkowym fragmencie nazwy ścieżkowej pliku (domyślnie jest to katalog bieżący). W obydwu przypadkach, jeśli bash odnajdzie kilka pasujących nazw, to wyświetla ich listę dając użytkownikowi możliwość wyboru.

Po zakończeniu edycji użytkownik zatwierdza polecenie wciskając [Enter].

(1.4) Wartościowanie i wykonywanie poleceń

Każde polecenie wydane przez użytkownika jest analizowane przez interpreter, rozwijane do pełnej postaci i dopiero wykonywane. Interpreter wykonuje kolejno następujące operacje:

  • podstawia wartości zmiennych (interpretacja znaku $),
  • podstawia wyniki poleceń (interpretacja znaków ``),
  • dokonuje podziału na nazwę polecenia i argumenty (interpretacja separatorów),
  • wykonuje przekierowanie strumieni danych,
  • rozwija nazwy plików,
  • rozpoznaje i wykonuje polecenie.
Jeśli interpreter rozpozna nazwę funkcji lub wbudowanego polecenia, to sam je wykonuje. Jeżeli rozpozna nazwę programu lub skryptu, to uruchamia go jako nowy proces potomny.

Każde polecenie zwraca swój status zakończenia. Przyjęto konwencję, że zerowy status oznacza pomyślne zakończenie, zaś wartość niezerowa jest zwracana, gdy polecenia nie udało się wykonać. Jeśli polecenie zostało przerwane przez sygnał o numerze n, to zwracana jest wartość 128 + n.

(1.5) Historia wydawanych poleceń

Interpreter może przechowywać listę ostatnio wydanych poleceń i udostępniać je użytkownikowi do powtórnego wykorzystania. Mechanizm ten nosi nazwę historii poleceń.

Oryginalna powłoka Bourne'a `sh` nie ma wbudowanego mechanizmu historii.

Powłoka bash udostępnia historię poleceń, jeśli ustawiona jest opcja history (patrz punkt 2.5). Liczbę pamiętanych poleceń określa zmienna HISTSIZE ustawiana domyślnie na wartość 500. Po uruchomieniu, bash zaczyna pracę z pustą listą historii, ale może ją zainicjować z pliku określonego zmienną HISTFILE. Domyślnie jest to plik ~/.bash_history. Maksymalną liczbę linii w pliku określa zmienna HISTFILESIZE.

Aktualną listę historii można wypisać poleceniem history. Każde z zapamiętanych poleceń poprzedzone jest swoim numerem. Posługując się tym numerem lub początkowym fragmentem nazwy, można przywołać konkretne polecenie w następujący sposób:

!identyfikator - ogólna postać odwołania do historii poleceń,
!! - przywołuje ostatnie polecenie,
!n - przywołuje polecenie o numerze n,
!-n - przywołuje polecenie położone n pozycji od końca listy czyli od ostatniego polecenia,
!string - przywołuje polecenie rozpoczynające się ciągiem znaków string.

Istnieje też drugi sposób korzystania z historii poleceń, który w większości przypadków jest znacznie wygodniejszy.
Powłoka bash umożliwia przeglądanie listy w linii poleceń przy użyciu kursorów ARROW_U.GIF oraz ARROW_D.GIF. Przywołane polecenie można potem modyfikować jak opisano w punkcie 1.3.

(1.6) Aliasy

Istotne ułatwienie do wielokrotnego posługiwania się złożonymi poleceniami wnoszą aliasy. Umożliwiają zastąpienie wieloczłonowego polecenia pojedyńczym wyrazem. Nową nazwą można się posługiwać tak, jak każdym innym poleceniem, dodając opcje i argumenty. Nie ma jednak możliwości wstawienia zmiennych argumentów do tekstu samego aliasu.

Mechanizm aliasów jest dostępny w większości interpreterów (z wyjątkiem `sh`), ale tylko w tych egzemplarzach, które zostały uruchomione w trybie interaktywnym. W związku z tym aliasy nie są na ogół dostępne w skryptach.

Każda uruchomiona powłoka przechowuje niezależnie własną listę aliasów zdefiniowanych przy pomocy wbudowanego polecenia:

alias [-p] [nazwa=wartość ...]
alias [nazwa ...]

Polecenie wywołane bez argumentów lub z opcją -p wypisuje pełną listę aliasów. Jeśli podane są tylko nazwy aliasów, powłoka wypisuje ich wartości. Dla argumentów w postaci nazwy z przypisaną wartością tworzone są nowe aliasy. Jeżeli przypisywana wartość składa się z kilku wyrazów (np. polecenie z opcjami i argumentami), to należy podać ją w cudzysłowach bądź apostrofach np.:

alias ll="ls -l"

alias l='ls -FC'

Aliasy zwykle ustawiane są w plikach konfiguracyjnych odczytywanych przez powłoki interaktywne, czyli w plikach: /etc/bashrc i ~/bashrc.

Usuwanie aliasów umożliwia polecenie:

unalias [-a] [nazwa ...]
<dl>

Konfigurowanie interpretera

</span>

Sposób działania interpretera jest w dużym stopniu ustalany przez parametry i opcje.

(2.1) Parametry

Parametry są instancjami przechowującymi wartości. Mogą być reprezentowane przez nazwę w postaci ciągu znaków, liczbę naturalną lub jeden ze znaków specjalnych.

Parametry reprezentowane przez liczbę naturalną noszą nazwę parametrów pozycyjnych i przechowują argumenty wywołania powłoki.

Parametry specjalne mają postać pojedyńczych znaków specjalnych a ich wartości są automatycznie ustawiane i modyfikowane dynamicznie przez powłokę.

Parametry reprezentowane przez nazwę określane są jako zmienne. Ustawianie wartości zmiennych odbywa się za pomocą jednego z trzech poleceń:

zmienna=[wartość]
typeset zmienna=[wartość]
declare zmienna=[wartość]

Jeśli wartość zostanie pominięta, to zmiennej zostanie przypisany zerowy ciąg znaków.

Usunięcie zmiennej umożliwia polecenie:

unset zmienna

Zmienne można podzielić na dwie kategorie:

  1. zmienne środowiska,
  2. zmienne lokalne powłoki.
Listę wszystkich zmiennych, zarówno lokalnych jak i środowiska, uzyskamy poleceniem:
`set`

Odwołanie do wartości dowolnego parametru następuje za pomocą znaku $ w następujący sposób:

`$parametr`
`${parametr}`

Postać z nawiasami jest konieczna, gdy w poleceniu bezpośrednio za nazwą parametru chcemy umieścić inne znaki oraz gdy nazwa liczbowa składa się z więcej niż jednej cyfry.

Przykład

`[apw@venus]$ x=abc
[apw@venus]$ echo $x
abc
[apw@venus]$ echo $x123`

`[apw@venus]$ echo ${x}123
abc123`

(2.2) Zmienne środowiska

Każdy tworzony proces, w tym również każda powłoka, otrzymuje nowe środowisko w postaci tablicy zawierającej ciągi znaków zmienna=wartość. Każdy taki ciąg oznacza utworzenie nowej zmiennej środowiska.

Ten początkowy zestaw zmiennych środowiska jest dziedziczony po procesie macierzystym, którym najczęściej jest powłoka uruchamiająca nowy program.

W trakcie działania procesu środowisko może być modyfikowane poprzez usuwanie i dodawanie nowych zmiennych oraz przez zmiany ich wartości. Wszystkie modyfikacje znajdują odzwierciedlenie we wspomnianej tablicy. Zmiany te jednak nie przenoszą się do procesu macierzystego. Zasada ta dotyczy również procesów potomnych danego procesu utworzonych przed modyfikacją środowiska.

Zmienne środowiska wyróżnia więc to, że nie są związane tylko z lokalną powłoką, ale są dziedziczone przez wszystkie procesy potomne tworzone przez powłokę.

Są wykorzystywane przez różne procesy a nie tylko przez proces powłoki. Nie można ich jednak traktować jako zmienne globalne, gdyż nie stają się widoczne dla wszystkich procesów.

Całe środowisko można wyświetlić przy pomocy poleceń:

printenv

lub

env

Wartość pojedyńczej zmiennej wypisze polecenie:

echo $zmienna

Dodanie do środowiska nowej zmiennej polega na wyeksportowaniu zmiennej lokalnej, której trzeba wcześniej przypisać właściwą wartość:

zmienna=wartość
export zmienna

Można to również zrobić w jednym etapie wydając polecenie:

export zmienna=wartość

Zmienną środowiska można usunąć poleceniem `unset`, podobnie jak zmienną lokalną.

W tablicy 4.1 zebrano najważniejsze zmienne środowiska definiowane w każdej powłoce i wyjaśniono ich znaczenie dla powłoki i innych procesów.

Tablica 4.1 Najważniejsze zmienne środowiska</span></caption> <font size="+1"> Nazwa zmiennej</span> </td> <font size="+1"> Znaczenie</span> </td> </tr> LOGNAME</td> Nazwa zalogowanego użytkownika.</td> </tr> USER</td> Nazwa zalogowanego użytkownika.</td> </tr> HOME</td> Katalog domowy zalogowanego użytkownika.</td> </tr> LANG</td> Język lokalny.</td> </tr> PATH</td> Ścieżka poszukiwań programów.</td> </tr> CDPATH</td> Ścieżka poszukiwań katalogów.</td> </tr> MANPATH</td> Ścieżka poszukiwań dokumentacji systemowej.</td> </tr> LD_LIBRARY_PATH</td> Ścieżka poszukiwań bibliotek dynamicznych.</td> </tr> PWD</td> Katalog bieżący.</td> </tr> SHELL</td> Powłoka uruchamiana po zalogowaniu użytkownika.</td> </tr> TERM</td> Typ terminala.</td> </tr> MAIL</td> Skrzynka pocztowa zalogowanego użytkownika.</td> </tr> MAILCHECK</td> Częstotliwość sprawdzania skrzynki pocztowej.</td> </tr> IFS</td> Wejściowy separator pola.</td> </tr> TZ</td> Strefa czasowa.</td> </tr> </table>

(2.3) Zmienne lokalne powłoki

Zmienne lokalne mają znaczenie wyłącznie dla bieżącej powłoki i tylko w niej są widoczne. Nie podlegają dziedziczeniu i nie mogą być wykorzystane przez inne procesy. Sposób definiowana i usuwania zmiennych opisano powyżej. W tablicy 4.2 opisane zostały wybrane zmienne powłoki.

<font size="+1">Tablica 4.2 Wybrane zmienne lokalne powłoki bash</span> </caption> <font size="+1">Nazwa zmiennej</span> </td> <font size="+1">Znaczenie</span> </td> </tr> BASH</td> Pełna nazwa ścieżkowa interpretera poleceń.</td> </tr> HISTFILE</td> Nazwa pliku przechowującego historię wydawanych poleceń.</td> </tr> HISTFILESIZE</td> Maksymalna liczba linii w pliku historii poleceń.</td> </tr> HISTSIZE</td> Liczba pamiętanych poleceń.</td> </tr> PS1</td> Podstawowy komunikat gotowości powłoki wyświetlany, gdy powłoka jest gotowa do przyjęcia kolejnego polecenia.</td> </tr> PS2</td> Wtórny komunikat gotowości powłoki wyświetlany, gdy powłoka oczekuje na dokończenie polecenia w następnej linii.</td> </tr> </table>

Zmienne PS1 i PS2 mogą być również ustawione jako zmienne środowiska. Definiują one sposób, w jaki powłoka zgłasza gotowość do dalszej pracy. Jeśli powłoka jest gotowa do przyjęcia kolejnego polecenia, to wyświetla komunikat gotowości zawierający ciąg znaków przypisany zmiennej PS1. Jeśli powłoka wymaga jeszcze dodatkowych danych wejściowych, żeby dokończyć polecenie, to wyświetla ciąg znaków przypisany zmiennej PS2. Podstawowe komunikaty zawierają tylko jeden znak, odpowiednio $ lub >. Stąd wywodzi się inna nazwa takiego komunikatu - znak zachęty powłoki. Najczęściej stosuje się jednak dłuższe komunikaty, które mogą zawierać nazwę komputera, nazwę użytkownika, nazwę bieżącego katalogu czy numer polecenia.

Przykład

Poniżej przedstawiono przykładowe wartości zmiennych PS1 i PS2 oraz ich efekt w postaci komunikatów gotowości powłoki.

[apw@venus apw]$ echo $PS1

[\u@\h \W]\$

[apw@venus apw]$ echo $PS2

>

(2.4) Parametry specjalne
</p>

Każda powłoka ustawia automatycznie kilka parametrów specjalnych, których wartości zmieniają się w trakcie jej działania. W tablicy 4.3 przedstawiamy znaczenie tych parametrów.

Tablica 4.3 Parametry specjalne powłoki bash</span></caption> <font size="+1">Parametr</span> </td> <font size="+1">Znaczenie</span> </td> </tr> #</td> Liczba parametrów pozycyjnych.</td> </tr> *</td> Lista parametrów pozycyjnych w postaci jednego ciągu znaków.</td> </tr> @</td> Lista parametrów pozycyjnych w postaci oddzielnych ciągów znaków.</td> </tr> ?</td> Status zakończenia ostatnio uruchomionego polecenia.</td> </tr> $</td> PID bieżącej powłoki.</td> </tr> !</td> PID procesu ostatnio uruchomionego w tle.</td> </tr> -</td> Lista opcji bieżącej powłoki.</td> </tr> </table>

Parametr $? umożliwia sprawdzenie w skrypcie, czy jakieś polecenie zakończyło się pomyślnie. Parametr $$ zawiera identyfikator PID bieżącej powłoki, który można wykorzystać np. do stworzenia pliku tymczasowego o unikalnej nazwie.

(2.5) Parametry pozycyjne
</p>

Parametry pozycyjne reprezentowane są przez kolejne liczby naturalne.
Parametr $0 przechowuje nazwę powłoki lub nazwę skryptu. Parametry $1, $2, $3 ... przechowują kolejne argumenty. Odwołania do parametrów o wyższych numerach, składających się z kilku cyfr, wymagają użycia nawiasów klamrowych: ${10}, ${11} ... Powłoka bash nie ogranicza więc możliwości bezpośredniego dostępu do wszystkich parametrów, podczas gdy w powłoce sh istnieje ograniczenie tylko do pierwszych 9 parametrów: $1, ... $9 a dostęp do pozostałych otrzymuje się po przesunięciu.

Wszystkie parametry pozycyjne można jednocześnie przesunać w lewo o dowolną liczbę pozycji za pomocą polecenia:

shift [n]

Gdy argument nie jest podany, domyślnie następuje przesunięcie wszystkich parametrów o jedną pozycję. W rezultacie parametr $1 jest usuwany (bezpowrotnie), parametr $2 przesuwa się na $1, parametr $3 na $2 itd. W przypadku gdy parametr n jest podany przesuwanie argumentów następuje o n pozycji, tzn. n pierwszych argumentów jest usuwanych a pozostałe zajmują pozycje zaczynając od $1.

Parametr $0 nigdy nie podlega przesunięciu i zawsze przechowuje nazwę.

Powłoka ustawia również trzy parametry specjalne związane z parametrami pozycyjnymi. Parametr $# określa liczbę ustawionych parametrów pozycyjnych z wyjatkiem parametru $0. Parametr $* przechowują całą listę parametrów pozycyjnych w postaci jednego ciągu znaków "$1 $2 $3 ...", natomiast $@ przechowuje tę listę w postaci oddzielnych ciągów "$1" "$2" "$3" ...

Początkowe ustawienie parametrów pozycyjnych można zmienić poleceniem:

set arg1 arg2 arg3 ...

Polecenie zmienia na raz wszystkie parametry pozycyjne, usuwając stare wartości i przypisując części z nich nowe wartości podane w poleceniu. Nie ma możliwości zmiany tylko wybranych parametrów.

(2.6) Opcje
</p>

Dodatkową możliwość konfiguracji interpretera zapewniają opcje. Można je ustawić podając odpowiednie argumenty przy wywołaniu powłoki albo w trakcie jej działania posłużyć się poleceniem:

set -o [opcja ...]

Polecenie wydane bez argumentów wypisuje aktualne ustawienia poszczególnych opcji.

Usuwanie opcji umożliwia polecenie:

set +o [opcja ...]

Większość opcji ma swoje jednoliterowe odpowiedniki, których można użyć przy uruchamianiu powłoki. Niektóre opcje są domyślnie ustawiane przez powłokę. W tablicy 4.4 podano nazwy, skróty literowe oraz znaczenie wybranych opcji:

Tablica 4.4 Wybrane opcje powłoki bash</span></caption> <font size="+1">Nazwa opcji
(skrót literowy)
</span> </td> <font size="+1"> Znaczenie</span> </td> </tr> history</td> Powłoka udostępnia mechanizm historii. W powłokach interaktywnych jest ustawiona domyślnie.</td> </tr> ignoreeof</td> Ignorowanie przez powłokę znaku końca pliku (ctrl d).</td> </tr> monitor (-m)</td> Powłoka udostępnia sterowanie pracami.</td> </tr> noclobber (-C)</td> Powłoka nie nadpisuje istniejących plików w wyniku przekierowania strumieni (>, >&). Można wymusić nadpisanie poprzez użycie >!.</td> </tr> notify (-b)</td> Powłoka natychmiast informuje o zakończeniu procesu w tle. Gdy opcja nie jest ustawiona, wypisuje informacje po wydaniu następnego polecenia.</td> </tr> noglob (-f)</td> Powłoka nie rozwija nazw plików zawierających znaki specjalne.</td> </tr> emacs</td> Powłoka używa stylu edytora emacs do edycji linii poleceń. Dopuszczane jest przemieszczanie się kursorami i wstawianie znaków.</td> </tr> vi</td> Powłoka używa stylu edytora vi do edycji linii poleceń. Opcja ta wyklucza się wzajemnie z opcją emacs.</td> </tr> xtrace (-x)</td> Powłoka wypisuje każde polecenie w postaci rozwiniętej przed jego wykonaniem. Umożliwia w ten sposób śledzenie wykonywania poleceń.</td> </tr> </table>

Interpretacja znaków specjalnych przez powłokę

</span>
(3.1) Rozwijanie nazw plików
</p>

Każdy interpreter dopuszcza stosowanie w nazwach plików specjalnych znaków, które mogą zastępować jeden lub więcej dowolnych znaków. Otrzymuje się w ten sposób wzorce pasujące do nazw kilku plików. Poniżej przedstawiono zestaw znaków specjalnych powłoki bash:

? - zastępuje jeden dowolny znak,
* - zastępuje dowolny ciąg znaków,
[ ] - zastępuje jeden znak z listy podanej wewnątrz nawiasów,
[ - ] - zastępuje jeden znak z zakresu podanego wewnątrz nawiasów,
[ ] lub [! ] - zastępuje dowolny znak oprócz tych podanych wewnątrz nawiasów.

Przykład.

ls *.[hc]

(3.2) Cytowanie
</p>

Cytowanie stosowane jest w celu usunięcia specjalnego znaczenia niektórych znaków i słów. Zapobiega interpretacji tych znaków przez powłokę, przywracając ich podstawowe znaczenie. Niektóre sposoby cytowania dopuszczają pewne wyjątki:

<font size="+1">\</span> - zapobiega interpretacji następnego znaku,
<font size="+1">" "</span> - zapobiegają interpretacji wszystkich znaków zawartych wewnątrz cudzysłowów, z wyjątkiem znaków $ i ``,
<font size="+1">' '</span> - zapobiegają interpretacji wszystkich znaków zawartych wewnątrz apostrofów,
<font size="+1">` `</span> - wykonuje polecenie zawarte wewnątrz znaków i wstawia w to miejsce strumień wyjściowy tego polecenia.

Przykład.

echo "`date` $pwd"

(3.3) Grupowanie poleceń
</p>

Interpreter umożliwia jednoczesne wydanie kilku poleceń w jeden linii. Sposób zgrupowania zdecyduje o tym, w jaki sposób i w jakiej kolejności powloka wykona te polecenia. Poniżej przedstawiono kilka możliwości połączenia poleceń w jednej linii oraz efekty takiego użycia (skrót cmd oznacza dowolne polecenie):

cmd ; cmd ; cmd - powłoka grupuje polecenia na pierwszym planie wykonując je sekwencyjnie,
cmd & cmd & cmd & - powłoka grupuje polecenia w tle wykonując je asynchronicznie,
cmd | cmd | cmd - powłoka grupuje polecenia wykonując je w potoku,
(cmd ; cmd) - powłoka grupuje polecenia i wykonuje w nowej powłoce,
{ cmd ; cmd ; } - powłoka grupuje polecenia i wykonuje w bieżącej powłoce, tworzy jeden strumień wyjściowy dla całej grupy poleceń i zwraca jeden status zakończenia.

(3.4) Przekierowanie strumieni
</p>

Powłoka związuje z każdym tworzonym procesem trzy strumienie danych:

  1. standardowy strumień wejciowy stdin,
  2. standardowy strumień wyjciowy stdout,
  3. standardowy strumień błędów (diagnostyczny) stderror.
Każdy ze strumieni związany jest z plikiem zwykłym lub z plikiem urządzenia wejścia/wyjścia. Domyślnym przywiązaniem dla wszystkich strumieni jest plik terminala.

Każdy plik otwarty przez proces otrzymuje kolejny numer zwany deskryptorem pliku. Deskryptory 0, 1 i 2 zarezerwowane są dla plików związanych ze standardowymi strumieniami.

Przed wykonaniem dowolnego polecenia można zmienić domyślne przywiązanie strumieni, czyli przekierować wejście i wyjście z polecenia. Przekierowania strumieni w powłoce bash obejmują następujące operacje:

[d]<plik - przekierowanie wejścia powoduje otwarcie pliku do czytania z deskryptorem d; jeżeli d zostało pominięte przyjmowane jest 0,
[d]>plik - przekierowanie wyjścia powoduje otwarcie pliku do pisania z deskryptorem d; jeżeli d zostało pominięte przyjmowane jest 1,
[d]>>plik - przekierowanie wyjścia powoduje otwarcie pliku do dopisywania z deskryptorem d; jeżeli d zostało pominięte, przyjmowane jest 1,
[d]<>plik - przekierowanie powoduje otwarcie pliku do czytania i pisania z deskryptorem d,
&>plik lub >&plik - przekierowanie powoduje skierowanie strumienia wyjściowego i strumienia błędów do tego samego pliku,
[d1]>&d2 - przekierowanie powoduje zduplikowanie deskryptora pliku wyjściowego; deskryptor d1 staje się kopią deskryptora d2 i wskazuje na ten sam plik.

Jeżeli numer deskryptora d zostanie pominięty, to powłoka domyślnie przyjmie deskryptor 0 (stdin) lub 1 (stdout) w zależności od rodzaju przekierowania.

Operatory przekierowania można umieścić w linii polecenia zarówno przed jak i za poleceniem. Przekierowania wykonywane są w kolejnosci występowania licząc od lewej do prawej.

(3.5) Inne
</p>

Interpreter korzysta jeszcze z kilku innych znaków specjalnych, które zostały już wprowadzone we wcześniejszej części tego podręcznika Dla przypomnienia przytaczamy je również w tym miejscu:

spacja, tabulator, znak nowej linii - separatory rozdzielające poszczególne elementy polecenia,
~ - katalog domowy użytkownika,
$ - podstawienie wartości parametru (zmiennej),
! - odwołanie do mechanizmu historii.

Skrypty

</span>

Plik tekstowy zawierający listę poleceń dla interpretera nosi nazwę skryptu. Skrypty tworzone są w celu ułatwienia użytkownikom pracy z interpreterem. Umożliwiają zapisanie często używanych sekwencji poleceń i zastąpienie ich jednym poleceniem uruchomienia skryptu. Są szczególnie przydatne dla administratora systemu, który wielokrotnie wykonuje powtarzające się czynnosci, takie jak zakładanie kont nowym użytkownikom, tworzenie kopii zapasowych.

Skrypt może zawierać:

  • odwołania do zmiennych,
  • wbudowane polecenia interpretera,
  • pętle sterujące,
  • wywołania programów i innych skryptów,
  • komentarze.
Wszystkie linie rozpoczynających się od znaku #, traktowane są przez powłokę jako komentarz i w związku z tym są ignorowane.

(4.1) Argumenty wywołania
</p>

Argumenty wywołania skryptu przekazywane są do powłoki jako parametry pozycyjne. Parametr $0 zawsze wskazuje nazwę skryptu, zaś parametry $1, $2, ... przechowują kolejne argumenty. Nazwa skryptu nie podlega przesunięciu w wyniku działania polecenia shift.

(4.2) Metody uruchamiania skryptów

Skrypt zawiera listę poleceń, które powinień wykonać interpreter. Istnieje kilka sposobów uruchomienia skryptu.

Naturalnym sposobem jest jawne wywołanie nowego interpretera z pierwszym argumentem w postaci nazwy skryptu:

sh skrypt arg ...
bash skrypt arg ...

Wygodniej jest jednak posługiwać się wyłącznie nazwą skryptu jako nazwą nowego polecenia. W tym celu należy wcześniej ustawić prawo wykonywania skryptu:

chmod +x skrypt
skrypt arg ...

Powstaje problem wyboru interpretera, który wykona skrypt. A wybór ten nie jest dowolny, gdyż każda powłoka stosuje inną składnię. Domyślnie uruchamiana jest powłoka sh. Użytkownik może wskazać dowolny interpreter umieszczając jego pełną nazwę ścieżkową w pierwszej linii skryptu po znakach #!, np.: #!/bin/bash.

W obydwu powyższych przypadkach uruchamiany jest nowy proces interpretera, który wykonuje polecenia zawarte w skrypcie, po czym kończy swoje działanie. Sterowanie wraca do procesu interpretera, w którym wydano polecenie. Nie są w nim widoczne zmiany dokonane w skrypcie takie, jak modyfikacja zmiennych czy zmiana bieżącego katalogu.

Skrypt może być również wykonany przez bieżący interpreter i wtedy wszystkie zmiany pozostają widoczne po zakończeniu skryptu. Służy do tego polecenie . (w powłokach sh i bash)) lub source (w powłoce bash):

. skrypt arg ...
source skrypt arg ...

Typowym zastosowaniem tej metody jest ponowne odczytanie plików konfiguracyjnych powłoki po wprowadzeniu modyfikacji, np:

. .bashrc

source .cshrc

Skrypt można wreszcie uruchomić zamiast bieżącego interpretera, posługując się poleceniem exec:

exec skrypt arg ...

W tym przypadku proces interpretera, który ma wykonać skrypt, zastępuje bieżący interpreter. Po zakończeniu działania skryptu nie istnieje już proces, w którym wydano polecenie. Sterowanie przechodzi więc do procesu nadrzędnego (macierzystego) lub następuje wylogowanie z systemu.

Programowanie w języku powłoki

</span>
(5.1) Pętle i polecenia sterujące

Zestaw złożonych poleceń powłoki bash obejmuje większość typowych pętli i poleceń sterujących.

Pętla for wykonuje się raz dla każdego słowa z listy. Jeśli lista zostanie pominięta, pętla wykonuje się raz dla każdego ustawionego parametru pozycyjnego.

`<font color="#0000cd">for zmienna [in słowo ...]
do lista_poleceń
done</font>`

Pętla for może przyjąć również drugą postać, w której:

  • wyrażenie1 określa warunek początkowy i obliczane jest tylko raz przed pierwszą iteracją pętli,
  • wyrażenie2 pełni rolę warunku zakończenia pętli i obliczane jest na początku każdej iteracji dopóki nie osiągnie wartość zerowej,
  • wyrażenie3 obliczane jest w każdej iteracji pętli po wykonaniu listy poleceń.


`for`` ((wyrażenie1; wyrażenie2; wyrażenie3))``
``do`` lista_poleceń``
``done`

Pętla while wykonywana jest dopóki ostatnie polecenie z listy warunków zwraca status zerowy.

`<font color="#0000cd">while lista_warunków
do lista_poleceń
done</font>`

Pętla until wykonywana jest dopóki ostatnie polecenie z listy warunków zwraca status niezerowy.

`<font color="#0000cd">until lista_warunków
do lista_poleceń
done</font>`

Polecenie case stara się dopasować słowo kolejno do każdego wzorca i wykonuje listę poleceń związaną z pierwszym pasującym wzorcem.

`<font color="#0000cd">case słowo in
wzorzec [|wzorzec] ...) lista_poleceń;;
...
esac</font>`

W poleceniu if wykonywana jest gałąź, dla której ostatnie polecenie z listy warunków zwraca status zerowy.

`<font color="#0000cd">if lista_warunków
then lista_poleceń
[elif lista_warunków
then lista_poleceń]
...
[else lista_poleceń]
fi</font>`

Pętle for, while i until mogą być przerywane za pomocą poleceń: break [n] i continue [n] Polecenie break przerywa wykonywanie pętli. Polecenie continue przerywa wykonywanie bieżącej iteracji pętli i wznawia następną iterację. Obydwa polecenia przerywają n poziomów zagnieżdżonych pętli, gdy podany jest argument. Domyślnie przyjmowane jest n=1.

Zakończenie działania powłoki umożliwia polecenie: exit [status] Argument oznacza status zakończenia zwracany przez powłokę. Domyślnie zwracany jest status zerowy.

(5.2) Sprawdzanie warunków
</p>

Polecenia sterujące if, while i until wykorzystują jako warunek działania status zakończenia innego polecenia. Może to być dowolne polecenie systemu Linux. Najczęściej najbardziej praktyczne okazuje się klasyczne sprawdzenie jakiegoś warunku np. porównanie dwóch liczb lub ciągów znaków. Takich możliwości dostarcza wbudowany w powłokę mechanizm sprawdzania warunków:

`<font color="#0000cd">[[ warunek ]]</font>`
oraz polecenie test, które można wywołać na dwa sposoby;
`<font color="#0000cd">test warunek</font>`
`<font color="#0000cd">[ warunek ]</font>`
We wszystkich przypadkach składnia specyfikowania warunku jest podobna. Istnieje możliwość sprawdzania atrybutów plików, porównywania ciągów znaków i liczb całkowitych. Liczby rzeczywiste traktowane są jak ciągi znaków.

Testowanie atrybutów pliku wygląda następująco:

`-r plik` - sprawdza, czy użytkownik posiada prawo do czytania,
`-w plik` - sprawdza, czy użytkownik posiada prawo do pisania,
`-x plik` - sprawdza, czy użytkownik posiada prawo do wykonywania,
`-f plik` - sprawdza, czy `plik `to plik zwykły,
`-d plik` - sprawdza, czy `plik `to katalog,
`-c plik` - sprawdza, czy `plik `to plik specjalny znakowy,
`-b plik` - sprawdza, czy `plik `to plik specjalny blokowy,
`-p plik` - sprawdza, czy `plik `to plik FIFO,
`-s plik` - sprawdza, czy `plik `to plik o niezerowej długości.



Przykład
Sprawdzanie, czy użytkownik posiada prawo pisania w katalogu dir.

if [ -w dir ]
then
mkdir nowy_katalog
fi


Testowanie ciągów znaków wygląda następująco:

`s1` - sprawdza, czy ciąg jest niezerowy,
`s1 = s2` - sprawdza, czy ciągi są identyczne,
`s1 != s2` - sprawdza, czy ciągi są różne.



Przykład
Sprawdzanie, czy bieżącym katalogiem jest katalog domowy użytkownika.

if [ $pwd=$HOME ]
then
mkdir nowy_katalog
fi


Porównywanie liczb całkowitych umożliwiają operatory:

`n1 -eq n2` - sprawdza czy n1 = n2,
`n1 -ne n2` - sprawdza czy n1 >< n2,
`n1 -gt n2` - sprawdza czy n1 > n2,
`n1 -ge n2` - sprawdza czy n1 >= n2,
`n1 -lt n2` - sprawdza czy n1 < n2,
`n1 -le n2` - sprawdza czy n1 <= n2.

Przykład
Wypisywanie kolejno argumentów wywołania skryptu.

while [ $# -gt 0 ]
do
echo $1
shift
done

Warunki można ze sobą łączyć korzystając z następujących operatorów logicznych:

-a - operator AND,
-o - operator OR,
( ) - grupowanie warunków.

(5.3) Operacje arytmetyczne

Niektóre interpretery, jak sh i csh, nie mają wbudowanych żadnych operacji arytmetycznych. Powłoka bash udostępnia możliwość rozwijania wyrażeń arytmetycznych bezpośrednio w poleceniach:

$((wyrażenie))
oraz poprzez wbudowane polecenie let:
let wyrażenie [wyrażenie ...]
Każdy argument polecenia let traktowany jest jako oddzielne wyrażenie, które należy niezależnie obliczyć. Wyrażenie może zawierać jedynie argumenty całkowite i operatory. Zestaw dostępnych operatorów oraz priorytety poprzedzania są identyczne jak w języku C. Poniżej przedstawiamy wybrane operatory, zaś pełną listę można znaleźć w dokumentacji elektronicznej lub w literaturze.

Wybrane operatory przedstawiono w tablicy 4.5:

Tablica 4.5 Operatory polecenia let</span></caption>
<font size="+1">Kategoria operatorów</span>
</td>
<font size="+1">Operatory</span>
</td> </tr> arytmetyczne</td> ++, --, **, *, / , %, -, +</td> </tr> logiczne</td> !, &&, ||</td> </tr> bitowe</td> ~, <<, >>, &, </sup>, |</td> </tr> podstawienia</td> =, *=, /=, %=, +=, -=, <<=, >>=, &=, =, |=</td> </tr> porównania</td> <=, >=, <, >, ==, !=</td> </tr> </table>

Przykład
Obliczenia z wykorzystaniem poleceń powłoki bash.


[apw@venus]$ let x=5*6
[apw@venus]$ echo $x
30
[apw@venus]$ echo $((x=7*8))
56
[apw@venus]$ echo $x
56

Do przeprowadzenia operacji obliczeniowych można również wykorzystać program expr uruchamiany w następujący sposób:

`expr arg1 operator arg2 ...`
Program oblicza wartość podanego wyrażenia i wysyła do stdout. Podstawienia można dokonać niezależnie w powłoce:
zmienna=`expr wyrażenie`
Wszystkie argumenty i operatory w wyrażeniu muszą być rozdzielone znakami spacji. Operatory można podzielić na trzy grupy (tablica 4.6):
Tablica 4.6 Operatory polecenia expr</span></caption>
<font size="+1">Kategoria operatorów</span>
</td>
<font size="+1">Operatory</span>
</td> </tr> arytmetyczne</td> +, -, \*, /, %</td> </tr> porównania</td> =, !=, \>, \>=, \<, \<=</td> </tr> dopasowania</td> :</td> </tr> </table>

Niektóre operatory (np. *) są znakami specjalnymi i mogą zostać przedwcześnie zinterpretowane przez powłokę zamiast przez program expr. W związku z tym powinny być poprzedzone znakiem \, aby przekazać je bezpiecznie do programu expr. Operatory arytmetyczne działają na liczbach całkowitych. Operatory porównania zapewniają porównanie arytmetyczne liczb całkowitych lub porównanie leksykalne innych argumentów. Operator : umożliwia sprawdzenie ile znaków z podanego ciągu pasuje do wzorca:

`string : wzorzec`
Wzorzec może zawierać znaki specjalne. Zestaw dostępnych znaków specjalne jest taki jak dla programu grep.

Przykład
Wykorzystanie polecenia expr do wykonywania obliczeń.
x=`expr $x + 1

Wykorzystanie operatora : polecenia expr.
expr $1 : '.*'
expr $1 : '[0-9]*'

(5.4) Operacje wejścia/wyjścia
</p>

Powłoka bash umożliwia wczytywanie danych ze strumienia wejściowego i wypisywanie komunikatów do strumienia wyjściowego.

`read [opcje] [zmienna ...]`
Polecenie read odczytuje jedną linię ze strumienia wejściowego stdin. Następnie dokonuje podziału na wyrazy, stosując separatory zdefiniowane w zmiennej IFS i przypisuje kolejne wyrazy zmiennym podanym na liście argumentów.
`echo [opcje] [arg ...]`
Polecenie echo przesyła na standardowe wyjście stdout argumenty rozdzielone znakiem spacji. Argumentem może być dowolny ciąg znaków, zawierający również znaki specjalne powłoki, np. odwołania do zmiennych.
`printf format [arg ...]`
Polecenie printf wypisuje argumenty na standardowym wyjściu zgodnie z podanym formatem. Sposób formatowania jest identyczny jak w przypadku funkcji printf() języka C.

(5.5) Funkcje
</p>

Interpreter umożliwia definiowanie własnych funkcji:

[function] nazwa () {lista_poleceń;}

Odwołanie do funkcji następuje przez nazwę, podobnie jak do wszystkich poleceń. Funkcje są zawsze wykonywane przez bieżącą powłokę. Argumenty wywołania funkcji zostają ustawione jako parametry pozycyjne powłoki wyłącznie na okres wykonywania funkcji.

Przykład
Zdefiniowana poniżej funkcja wyświetla informacje o poprawnym wywołaniu skryptu

usage()
{
echo "Poprawne wywolanie to : nazwa_skryptu arg1 op1 arg2 ... "
echo "\nWywolania,operatory i realizowane dzialania "
echo "Dodawanie np: 2 + 3 "
echo "Odejmowanie np: 4 - 5 "
echo "Dzielenie np: 4 / 2 "
echo "Mnozenie np: 4 * 4 "
echo "Potegowanie np: 4 \</sup> 4"
exit
}


Autorami powyższego artykułu są mgr inż. A. Wielgus i dr Z. Jaworski. Drobnych zmian i poprawek dokonał Ł. Fronczyk
W dziale źródła/C++ znajdują się przykładowe programy do tego i pozostałych artykułów z tego cyklu.
Wszelkie pytania proszę kierować na adres [email protected]

2 komentarzy

artykuł jest ok, fajnie że ktoś zebrał wszystkie rzeczy , które mozna znalezc w necie do jednej kupy ...

Kawał dobrej roboty, mi się na pewno przyda.