ChangeBlog  •  Archiwum  •  Kategorie  •  Artykuły  •  Galeria  •  Czytelnicy  •  Rupieciarnia
RSS wpisów  |  RSS komentarzy
Shelle

Shell (pol. "powłoka") jest podstawowym narzędziem pracy z linuksem. Jest pośrednikiem między użytkownikiem a kernelem. Nawet jeśli użytkownik nie styka się bezpośrednio z shellem, to i tak ten shell gdzieś się przewija. Już przy starcie systemu, gdy tylko /sbin/init przeczyta /etc/inittab, uruchamiane są pierwsze instancje shelli.

Zadania jakie stawia się przed shellami są bardzo zróżnicowane. Z jednej strony współczesny shell powinien być nieduży, szybki i oczywiście zgodny z shellem Bourne'a (/bin/sh). Z drugiej strony shell powinien być wygodny, co wiąże się z koniecznością dodawania cech takich jak historia poleceń, tab-completion, zaawansowane funkcje edycyjne. Wiąże się to z powstawaniem dużej ilości kodu którego zadaniem nie jest już zapewnienie zgodności z /bin/sh, ale spełnianie zachcianek użytkownika. Zachcianek które nie wpływają w ogóle na wykonywanie zadań, ale są bardzo ważne dla wygody użytkownika.

Szybko wyłaniają się dwa modele shelli: Shell "skryptowy", którego zadaniem jest przetwarzanie skryptów i który pracuje zwykle niezauważony, oraz shell "interaktywny", czyli ten z którym użytkownik się bezpośrednio styka. Shell skryptowy powinien być jak najmniejszy i najszybszy, shell interaktywny z kolei jak najwygodniejszy.

W zasadzie każdy z shelli stara się jakoś pogodzić te dwa aspekty, ale rezultaty są różne. Stąd niektóre shelle nadają się lepiej do określonych zadań, inne zaś gorzej. Warto mieć świadomość mocnych i słabych stron narzędzia którego się używa. Ale jeszcze cenniejsza jest wiedza o dostępnych alternatywach, gdyż wtedy można świadomie wybrać narzędzie najbardziej odpowiadające naszym potrzebom. A ponieważ shell jest podstawowym narzędziem pracy z linuksem, to odpowiedni jego dobór rzutuje na całą pracę z tym systemem.

Bash. "Bourne Again Shell":

Jego cecha: Popularność.

Bash, jak rozwinięcie jego nazwy wskazuje, jest następcą powłoki Bourne'a. Jako że jego pierwowzór jest już dosyć wiekową konstrukcją, bash powprowadzał bardzo dużo zmian i modyfikacji do pierwotnej idei. Przede wszystkim dotyczą one pracy interaktywnej. Historia poleceń, edycja linii poleceń (używająca biblioteki readline), kilkanaście dodatków zaczerpniętych z innych uniksowych shelli.

Nie ma chyba sensu opisywanie cech basha - jest to standardowy shell, którego każdy linuksiarz zna - więc na tym przestanę. Warto jednak zauważyć jedno: cień basha, który zaległ nad linuksowym światkiem. Przez swoją popularność wielu linuksiarzy stawia znak równości pomiędzy "bash" i "shell". Niesłusznie, bo są inne, często lepsze powłoki. Dodatkowo popularność basha wywołała zjawisko tzw. "bashizmów" - bash oferuje swoje wersje niektórych funkcji powłoki Bourne'a i niektórzy użytkownicy tak przyzwyczaili się do tych "bashowych" wersji, że wydają im się one być jedynym możliwym rozwiązaniem. Rezultatem takiego spłyconego postrzegania są setki skryptów które wymagają #!/bin/bash, choć tak naprawdę znakomicie by sobie działały, bez żadnej utraty funkcjonalności, także na zwykłym /bin/sh. Inną cechą bashizmów jest to, że rozmywają one w społeczności pojęcie o tym co tak naprawdę umiał /bin/sh. Bash, jak i inne "duże" shelle zgodne z /bin/sh może pracować w różnych trybach, w zależności od sposobu wywołania. Gdy zostanie uruchomiony jako "bash" oferuje wszystkie swoje funkcje. Gdy zostanie uruchomiony jako "sh" teoretycznie ogranicza swoje "features" do tego, co oferuje standard powłoki Bourne'a. Teoretycznie, gdyż twórcy basha nie stanęli na wysokości zadania i nawet w trybie emulacji /bin/sh bash pozwala na pewne niestandardowe zachowania. Twórcy skryptów nawet jeśli starają się doprowadzić swoje dzieła do poziomu ogólnej zgodności z /bin/sh mogą mieć utrudnione zadanie, gdyż bash nie jest wystarczająco konsekwentny. I w innych shellach mogą przez to wystąpić problemy ze zgodnością. To jest ta druga strona bashizmów, która wyrządza więcej krzywdy - bo działa po cichu i niezauważenie.

tCsh. Ulepszona wersja "C-shell" z Berkeley:

Jego cecha: Alternatywność.

Tcsh to shell wywodzący się od csh. To, co go od razu wyróżnia to fakt, że nie próbuje nawet zachować zgodności z shellem Bourne'a. Oznacza to od razu jedno: tcsh nie nadaje się do uruchamiania standardowych skryptów. Potrafi interpretować skrypty napisane dla /bin/csh, ale te są rzadkością w światku linuksa. To, co odróżnia tcsh od csh to edycja linii poleceń, dopełnianie nazw plików i poleceń oraz inne dodatki. Gramatyka tej powłoki różni się znacznie od tej proponowanej przez /bin/sh, tcsh używa składni i konstrukcji podobnych do tych występujących w języku C (stąd i nazwa: "C-shell"). Jest to bardzo interesujący shell który nie ustępuje funkcjonalnością bashowi. Rozwój tego shella jest jednak ostatnio bardzo ograniczony i praktycznie nie liczy się on na "rynku linuksowych shelli". A szkoda. Co ciekawe tcsh, posiadał większą część swoich obecnych możliwości już dawno temu, w czasach gdy bash nie potrafił zbyt wiele. Nawet dzisiaj posiada kilka funkcji których nie uświadczy się w bashu - kolorowanie dopełnień, lewy i prawy prompt.

Jest to bardzo sympatyczny shell do pracy interaktywnej i może z powodzeniem zastępować tutaj basha - o ile użytkownik będzie w stanie przyzwyczaić się do zupełnie innej konstrukcji przypisywania wartości zmiennym środowiskowym, wyraźnie wydzielonych dwóch typów zmiennych (lokalne i środowiskowe, w bashu ten podział jest mocno rozmyty), całkowicie "niestandardowych" konstrukcji warunkowych czy pętli.

Ogólnie: Shell bez specjalnych wodotrysków, miejscami ustępuje bashowi, miejscami go przewyższa.

Ash. "A shell":

Jego cecha: Mały rozmiar.

Ash to miniaturowy shell którego jedyną ambicją jest zgodność z /bin/sh oraz utrzymanie jak najmniejszych rozmiarów. Praca interaktywna jest raczej wykluczona - nie ma historii poleceń, edycji linii poleceń, tab-completion, itp. Ale ma mniej niż 60KB i potrafi uruchomić skrypty przeznaczone dla /bin/sh. Więc nadaje się na interpreter skryptów lub jako shell na dyskietce ratunkowej, gdzie każdy kilobajt się liczy.

Sash. "Stand-alone shell":

Jego cecha: Wbudowane polecenia.

Sash to "shell ratunkowy". Nie jest jego zadaniem interpretować skrypty, nie ma też służyć do pracy interaktywnej. Sash powinien być skompilowany statycznie, ma wtedy zwykle rozmiar ponad 400KB. Jego silna strona tkwi we wbudowanych poleceniach - statyczny sash posiada wbudowane odpowiedniki takich poleceń jak chmod, chown, chroot, cmp, cp, dd, echo, ed, grep, file, find, gzip, ln, ls, mkdir, mknod, mount, more, mv, rm, rmdir, sync, tar. I jeszcze parę innych. Polecenia te są oczywiście okrojone w porównaniu z ich odpowiednikami GNU, ale sash jest wyśmienitym shellem do podnoszenia systemu ze stanu krytycznego - nie wymaga do działania żadnej biblioteki czy zewnętrznych programów, a pozwala wykonać dużą część koniecznych zadań. Warto używać wersji "sash-plus-patches", która posiada jeszcze kilka dodatków. Oczywiście nie posiada ani historii poleceń, ani tab-completion, ale w końcu nie takie jest jego przeznaczenie.

PDksh. "Public-Domain Korn Shell":

Jego cecha: Wysoka prędkość działania.

PDksh wzoruje się na ksh - "Korn shell". Standardowy "ksh" miał zbyt restryktywną licencję, więc powstał pdksh. Shell ten oferuje bardzo dobrze zrealizowaną pracę w trybie zgodności z /bin/sh, oprócz tego też stara się jak najlepiej emulować ksh (choć to drugie raczej niewielu interesuje). Shell nadaje się świetnie do uruchamiania skryptów, można go też używać w normalnej, interaktywnej pracy, choć nie oferuje on tutaj zbyt wiele.

Jego główną zaletą jest wysoka zgodność z /bin/sh i znakomite osiągi przy interpretowaniu skryptów (radzi sobie tutaj chyba najlepiej z wszystkich linuksowych shelli). A więc idealny wybór na /bin/sh.

Przeprowadziłem kiedyś testy porównawcze które ukazują przewagę pdksh nad konkurencją. Można je znaleźć w artykule <slrn.pl.arkt1c.2jr.grzegorz@quatrin.pl>

Zsh. "The Z Shell":

Jego cecha: Wygodna praca interaktywna.

Zsh jest shellem kompatybilnym z /bin/sh. Ale główny nacisk leży na zapewnieniu wygodnego środowiska do pracy interaktywnej. W Zsh zbierają się najlepsze cechy innych shelli. Znajdzie się tu funkcje zaczerpnięte z basha, ksh, tcsh, jak również sporo rzeczy które nie występują nigdzie poza Zsh. Shell ten jest największym spośród dostępnych na linuksie, więc raczej nie jest predestynowany do pracy jako /bin/sh. Ale świetnie sprawdza się w pracy interaktywnej.

Tym, co zwykle wymienia się jako cechę Zsh jest rozbudowany system tab-completion. Razem z "programowalnym dopełnianiem" możliwe jest dopełnianie dowolnych "obiektów", nie tylko nazw poleceń czy plików. Programowalne dopełnianie może dopełniać opcje poleceń, wybrane typy plików (np. mpg123 dopełniane jest tylko plikami .mp3), lub po prostu jakimiś obiektami (np. ssh może być dopełniane wpisami z /etc/hosts). Dla basha istnieje podobny projekt, "bash programmable completion", ale jest on zacofany w porównaniu z mechanizmami Zsh - zarówno jeśli idzie o możliwości, jak i liczbę obsługiwanych poleceń. Trudno jest mi opisać funkcjonowanie dopełniania w zsh - generalnie działa ono tak, że naciskając <Tab> dopełniane są pasujące do kontekstu obiekty.

Przykład z "umount":

Jeśli wpiszę "umount <Tab>", to zsh zaproponuje mi listę wszystkich podczepionych aktualnie filesystemów:

/ /dev/cdrom /dev/pts /proc /var/lock devpts procfs
/cdrom /dev/hda1 /dev/shm /shm /var/run lock run

Jeśli wpiszę "umount -<Tab>", to zsh zaproponuje mi pasujące w tej sytuacji opcje:

-V -- show version
-a -- unmount all file systems from /etc/mtab
-h -- show help
-n -- don't write /etc/mtab
-r -- remount read-only on failure
-t -- specify file system type
-v -- verbose mode

Jak widać, wystarczyło podanie minusa by zsh zrozumiał, że chodzi mi o podanie opcji. I odpowiednio dostosował swoje propozycje.

Przykład z xset:

Po wpisaniu "xset <Tab>":

+dpms -- enable DPMS
+fp -- prepend font path elements
-b -- disable bell
-bc -- disable bug compatibility
-c -- disable key click
-display -- display
-dpms -- disable DPMS
-fp -- remove font path elements
-k -- disable lock
-led -- turn off all LEDs
-r -- disable autorepeat
b -- specify bell parameters
bc -- enable bug compatibility
c -- control key click
dpms -- specify DPMS parameter
fp -- control font path
fp+ -- append font path elements
fp- -- remove font path elements
fp= -- set font path
k -- enable lock
led -- control keyboard LEDs
mouse -- specify mouse parameters
p -- specify pixel color values
q -- query current information
r -- enable autorepeat
s -- specify screen saver parameters

Hmm... po wpisaniu "xset fp<Tab>":

fp -- control font path
fp+ -- append font path elements
fp- -- remove font path elements
fp= -- set font path

Bardzo ładnie. No to jeszcze "xset fp-<Tab>":

/usr/share/fonts/FantasyTTF/ /usr/share/fonts/ISO8859-2/misc
/usr/share/fonts/ISO8859-2/100dpi /usr/share/fonts/XminFonts/misc
/usr/share/fonts/ISO8859-2/WinFonts/ /usr/share/fonts/artwiz

Jak widać Zsh dostosowywał swoje dopełnienia do zastanej sytuacji. Najpierw podał wszystkie dostępne opcje. Potem, gdy powiedziałem że chodzi mi o "fp" zawęził propozycje do tych, które miały sens w tamtej sytuacji. A gdy powiedziałem że idzie mi o "fp-", zaproponował listę wszystkich aktualnie aktywnych ścieżek z fontami.

Zsh potrafi robić "takie rzeczy" w większości sytuacji. Np. przy "rpm -e" będzie proponował nazwy zainstalowanych pakietów. Dla "make" będzie proponował nazwy obiektów z Makefile (czyli "all", "clean", "install", etc.). Dla ./configure będzie proponował odpowiednie "--with-*", "--without-*", "--prefix=". Oprócz tego ma całe to klasyczne dopełnianie nazw poleceń i nazw plików.

Cały mechanizm programowalnego dopełniania posługuje się tzw. pluginami - dla każdego polecenia można zdefiniować obsługujący je plugin. Pluginy są po prostu specjalnymi, shellowymi skryptami. Stąd i ich możliwości - mogą użyć dowolnych metod aby zebrać potrzebne tab-completion dane.

Dobrze, to by była ta najbardziej znana strona Zsh.