Obsah Varianty shellu...2 Základní pojmy...2 Jednoduché příkazy...3 Návratové kódy...3 Standardní vstupy a výstupy...3 Prázdný soubor...3 Kolony...3 Seznamy...4 AND (&&) / OR ( )...5 Závorkování...6 Zrušení řídícího významu speciálních znaků...7 Obrácené lomítko ( \ )...7 Apostrofy ( ` )...8 Uvozovky ( )...8 Expanze...8 Expanze jmen (*-expanze)...8 Expanze pomocí složených závorek...9 Skripty...9 Obsah skriptu...10 Proměnné...10 Parametry...11
UNIX Uživatelské rozhraní Shell je interpret programovacího jazyka. Čte příkazy z terminálu a provádí je. Jeho nejznámější varianta je tzv. Bourne shell, známý pod názvem sh. Známe ještě další varianty jako je ku příkladu GNU Bourneagain shell bash. Varianty shellu Uživateli se po přihlášení spustí ten shell (terminál), který je nastaven v jeho uživatelském záznamu v souboru /etc/passwd. Shell, který se použije jako první, se nazývá login shell a má výsadní postavení. Rozlišujeme interaktivní a neinteraktivní shell. Interaktivní shell má vstup a výstup napojen na terminál. Neinteraktivní je ten, který spouštíme aby četl skript ze souboru. Interaktivní shell jiného než login shell hledá v domovském adresáři konfigurační soubor.bashrc a pokud ho najde, tak ho spustí. Základní pojmy Definujme si následující základní pojmy: Bílé místo Je alespoň jednoznaková posloupnost mezer a tabulátorů. Slovo Je posloupnost znaků, která se v shellu považuje za samostatnou, dále nedělitelnou jednotku. Jméno Je slovo tvořené písmeny, číslicemi a znakem podtržení _. Jméno začíná buď písmenem nebo znakem _. Taktéž se nazývá identifikátorem. Metaznak Je znak kterým se oddělují slova. Je to jeden z těchto znaků: & ; ( ) < > mezera tabulator Řídící operátor Je slovo které vyvolá určitou řídící operaci. Jde o tato slova: & && ; ;; ( ) nový řádek Rezervovaná slova Jsou to slova, která mají v shellu zvláštní význam. Jde o tato slova:! case do done elif else esac fi for function if in select then until while { }
Jednoduché příkazy Jednoduchý příkaz je posloupnost slov oddělených bílím místem. První slovo určuje příkaz, který se provede. Ostatní slova se příkazu přiřadí jako argumenty (parametry). Příklad jednoduchého příkazu: cd adresar Návratové kódy Každý spuštěný binární program v systému UNIX po ukončení vrací návratový kód. Návratový kód je celé kladné číslo a hodnota 0 znamená, že vše proběhlo v pořádku. Hodnota, která není 0 znamená, že během vykonávání programu nastala chyba. Standardní vstupy a výstupy Každý program (proces) v UNIX-u má alespoň dva výstupy. První je standardní výstup a druhý je standardní chybový výstup. Tyto výstupy je možno přesměrovat. A to za pomoci znaku > nebo znaků 2>. Tento znak/-y stačí uvést za poslední argument příkazu. Příkaz ls >./soubor.txt vypíše obsah aktuálního adresáře do souboru soubor.txt, který bude uložen aktuálním adresáři. Chybový výstup však bude vypsán na obrazovku. Příkaz ls adr 2>./err.txt vypíše na obrazovku obsah adresáře adr a do souboru err.txt vypíše chybový výstup (například kdyby neexistoval adresář adr). Standardní výstup je také možno přesměrovat za pomoci operátoru >>. V tomto případe však nedochází k přepsání souboru jako u operátoru > a data jsou zapisována na konec souboru. Prázdný soubor V systému UNIX existuje soubor /dev/null, který reprezentuje zařízení, které je prázdné. Je možno si ho představit jako obdobu koše ze systému Microsoft Windows. Z tohoto zařízení se však nedají žádné soubory obnovit. Příkaz ls adr 2> /dev/null vypíše chybovou hlášku (pokud například adresář adr neexistuje) do prázdného zařízení a není vidět na výstupu na display. Kolony Kolona je posloupnost jednoho nebo více příkazů oddělených metaznakem. Formát zápisu je následovný: [!] příkaz1 [ příkaz2] Význam kolony je následující. Výstup z příkaz1 se použije pro vstup pro příkaz2. Je nutno si uvědomit, že všechny příkazy v koloně jsou spuštěny najednou a ukončují jse až když dostanou na vstup EOF což je speciální znak End Of File. Znak! představuje negaci návratového kódu. Negace znamená obyčejně obrácená hodnota. Negace návratového kódu 1 a více je 0 a negace návratového kódu 0 je 1.
Příklad: Příkaz ls jako takový vypisuje obsah adresáře. Příkaz more čte vstup a formátuje ho na oddělené řádky. Kolona ls more pracuje tak, že výpis příkazu ls naformátuje na samostatné řádky. Příklad 2: Příkaz grep vyhledává v daném vstupu řetězec a řádek vstupu na kterém je nalezen tento řetězec vypisuje na standardní výstup. Kolona ls lr grep jmenosouboru vytvoří v paměti procesy pro příkaz ls a příkaz grep příkaz ls s parametry l (podrobný výpis) R (rekurzivně na všechny podadresáře) začne vypisovat obsah daného adresáře a všech podadresářů na svůj standardní výstup. Tento výstup je přesměrován na vstup pro příkaz grep, který postupně prochází vstup a hledá v něm posloupnost znaků jmenosouboru. Jakmile najde takovouto posloupnost znaků v nějakém řádku, tak celý řádek vypíše na výstup cože je standardně obrazovka displaye. Seznamy Seznam je posloupnost jednoho nebo více kolon (příkazů) oddělených jedním z řídících operátorů & && ; A je ukončena jedním z následujících operátorů & ; nový řádek Pokud je příkaz ukončen operátorem &, shell jej provádí v kopii shellu na pozadí, nečeká se na dokončení příkazu. Pokud ale oddělíme příkaz za pomoci středníku ; tak bude shell vykonávat příkazy sekvenčně. Příklad: cd dir1&ls Spustí se zároveň příkaz cd a zároveň příkaz ls. Výsledek je takový, že příkaz cd se spustí na pozadí a v kopii shellu se změní adresář a potom se tato kopie shellu ukončí. Zatím se spustí příkaz ls a ten na obrazovku vypíše obsah právě prohlíženého adresáře. cd dir;ls Spustí se nejdříve příkaz cd, který změní pracovní adresář a po jeho dokončení se spustí příkaz ls, který vypíše na obrazovku obsah pracovního adresáře.
A B A AND B A OR B 1+ 1+ 1 1 1+ 0 1 0 0 1+ 1 0 0 0 0 0 AND (&&) / OR ( ) V praxi se často používají operace AND a OR. Pro přehlednost je zde vidět tabulka fungování AND a OR. V tabulce znamená hodnota 1+, že příkaz skončil s chybou a hodnota 0 že příkaz proběhl správně. Pokud kupříkladu skončil program A z chybou a program B také z chybou tak výsledná návratová hodnota operace AND bude 1 a operace OR také 0. Operace AND je reprezentována v systému UNIX operátorem && a operace OR je reprezentována operátorem. Systém UNIX se snaží získat hodnotu návratového kódu co nejdříve a tímto způsobem také vyhodnocuje jestli bude další příkaz v seznamu vyhodnocen. Příklad: Pokud budeme mít seznam OR ( ) a zápis bude následovný: příkaz1 příkaz2. Z tabulky je vidět, že pokud se p ř íkaz1 ukončí s návratovým kódem 0 tak už nezáleží na tom jakým návratovým kódem by skončil příkaz2. Návratová hodnota seznamu bude pořád 0 bez ohledu na návratový kód příkazy2. Proto systém UNIX ani nespustí příkaz2 a vrátí návratovou hodnotu 0. Pokud by p ř íkaz1 vrátil návratovou hodnotu 1 a více tak systém UNIX musí zjistit ještě hodnotu příkazu2 aby věděl vrátit celkový návratový kód seznamu a proto jakmile získá návratový kód příkazu1 spustí příkaz2 a počká na jeho dokončení a potom vrátí celkový návratový kód. Příklad2: Pokud budeme mít seznam AND (&&) a zápis seznamu bude následovný: příkaz1 && příkaz Opět je vidět z tabulky, že pokud p ř íkaz1 skončí s návratovou hodnotou 1 tak je možné bez znalosti návratového kódu příkazu2 vrátit hodnotu 1. Systém UNIX šetří výpočtový čas a nespustí ani příkaz2 a vrátí hodnotu 1. Naopak pokud by skončil příkaz1 s návratovou hodnotou 0 tak bez znalosti návratového kódu příkazu2 není možné vrátit celkovou návratovou hodnotu seznamu a proto UNIX jakmile se dokončí příkaz1 spustí příkaz2 a po jeho dokončení vrátí spočtenou hodnotu jako návratový kód seznamu. Jednoduchá poučka: Při použití OR se nevykonávají další příkazy první příkaz byl proveden bez chyb. Při použití AND se nevykonají další příkazy pokud první příkaz skončil s chybami.
Závorkování Seznam příkazů můžete uzavírat do závorek. Jsou dvě možnosti. (seznam) Tímto způsobem uzavřený seznam se vykoná v kopii shellu. Jakékoliv změny, či proměnné nastavené během tohoto nového shellu se ztrácejí. Jediné, co je možno získat je návratová hodnota seznamu uzavřeného v závorkách. { seznam;} Tímto způsobem uzavřený seznam se vykoná v právě běžícím shellu ze kterého je tento příkaz spuštěn. Návratovým kódem je návratový kód seznamu. Pozor na nezbytnost bílého místa po první závorce a středníku před poslední závorkou. Příklad: cd adresar { mkdir adresar; cd adresar;} Jako první se vykoná příkaz cd adresar. Na základe jeho návratové hodnoty (operace OR) se UNIX rozhodne jestli vykonávat seznam a získat jeho návratovou hodnotu. Pokud proběhne cd adresar v pořádku, tak se seznam nevykoná. Pokud proběhne s chybou tak se vykoná seznam { mkdir adresar; cd adresar;}. Příkaz mkdir adresar se pokusí vytvořit adresar. Bez ohledu na to jestli se mu to podaří se až po jeho ukončení (díky středníku ;) spustí příkaz cd adresar. Návratová hodnota seznamu je zde jeho poslední příkaz. Je tak protože se nejedná o OR nebo AND operátory uvnitř seznamu. Návratová hodnota seznamu v závorkách je návratová hodnota příkazu cd adresar. Návratová hodnota celého příkazu je návratová hodnota podle tabulky OR. Viz tabulka. Osvětlení tabulky: Pokud proběhne příkaz cd adresar s chybou tak se vykoná seznam. V seznamu se vykoná mkdir adresar a po něm se vykoná cd adresar. V našem případě se vykonal poslední cd adresář v pořádku (řádek s červeným písmem) a návratová hodnota seznamu je 0 a podle OR, 1+ 0 je 0. Celková návratová hodnota je 0.
A A OR B B = C ; D cd adresar B = C ; D C D mkdir adresar cd adresar 1+ 1+ 1+ 1+ 1+ 1+ 0 0 1+ 0 1+ 1+ 1+ 0 1+ 1+ 0 0 0 0 0 0 1+ 1+ 1+ 0 0 0 1+ 0 0 0 1+ 0 1+ 0 0 0 0 0 Příklad2 (zkuste si doma sami): Porovnejte si sami v čem se liší tyto dva příkazy: (pwd; cd adresar; pwd);pwd { pwd; cd adresar;pwd;};pwd Zrušení řídícího významu speciálních znaků Vzhledem k tomu, že někdy potřebujeme zadat speciální znak v shellu a potřebujeme aby byl chápán jako samostatný znak a ne jako řídící operátor, tak je nutné jeho řídící funkci potlačit. Takovýto případ je když potřebujeme vytvořit soubor s názvem JA&TY.txt. Pokud by jsme napsali touch JA&TY.txt tak by shell vykonal seznam příkazů JA (který neexistuje) a bez počkání na dokončení tohoto příkazu (díky operátoru &) by spustil příkaz TY.txt (který také neexistuje). Na potlačení řídícího významů operátorů se používají tři způsoby. Obrácené lomítko ( \ ) Obrácené lomítko \ se používá velice často. Jakýkoliv znak který je za obráceným lomítkem ztrácí svůj řídící význam. Lomítko ovlivňuje jenom znak bezprostředně za lomítkem. Speciální znak je je bílé místo. Sami si zkuste příkazy a zjistěte jak je důležité zakazovat řídící funkce operátorů: touch a b touch a\ b touch ja&ty.txt touch ja\&ty.txt mkdir ps&&ls mkdir \ \ ps\&\&ls
Apostrofy ( ` ) Uzavřením do apostrofů ztrácejí svůj řídící význam všechny řídící znaky kromě apostrofů. Ten do apostrofů uzavřít nelze. Zkuste si: touch ahoj&ps touch `ahoj&ps` Uvozovky ( ) Uzavřením znaků do dvojice uvozovek ztrácí řídící znaky svůj význam. Výjimkou jsou tyto znaky: $ \ Příklady: Zkuste si funkcionalitu následujících příkazů: echo \ echo \ echo \\ echo echo \ Expanze Expanze jmen (*-expanze) V prostředí UNIX je expanze za pomoci znaků *,? a [ ] je poměrně častá záležitost a bez této funkcionality by bylo se systémem velice obtížné pracovat. Ku příkladu pokud chcete odstranit veškeré soubory které se nachází ve složce není nic lehčího než napsat příkaz rm s parametrem *. Celková expanze funguje tak, že nejdříve se vytvoří seznam všech odkazů v adresáři a tento seznam se pak filtruje za pomoci operátorů * a?. Záměna * Hviezda (*) představuje jakýkoliv množství znaků, které po sobě jdou. Jedinou výjimkou jsou soubory, které začínají znakem tečka (.), soubory jako třeba.passwd, či.shadow nejsou operátorem * akceptovány. Záměna? Otazník (?) předstauje právě jeden a to jakýkoliv znak. Příklady pozitivně či negativně vyhodnocené expanze: Mějme adresář ve kterém jsou umístěny soubory a spouštíme příkaz ls s parametry lad postupně s dalším parametrem (*; *.*;.*;?.txt; *.txt; ahoj?.*;.*.????; 9?.*)
Název souboru * *.*.*?.txt *.txt ahoj?.*.*.???? 9?.* ahoj1.txt ANO ANO NE NE ANO ANO NE NE l.txt ANO ANO NE ANO ANO NE NE NE.shadow NE NE ANO NE NE NE NE NE.smile.face NE NE ANO NE NE NE ANO NE 92.pass ANO ANO NE NE NE NE NE ANO 83.pass ANO ANO NE NE NE NE NE NE ahoj ANO NE NE NE NE NE NE NE Expanze pomocí složených závorek Pro urychlení práce při operacích v příkazovém řádku je možné použit expanze za pomoci seznamů. Seznam slov pro nahrazení je vždy uzavřen ve složených závorkách { } a slova uvnitř jsou oddělena za pomoci symbolu čárky (, ). Uveďme příklad: mkdir /usr/local/src/typo/{bad,good,lame,top,bottom} Je po expanzi převeden na sérii příkazů: mkdir /usr/local/src/typo/bad mkdir /usr/local/src/typo/good mkdir /usr/local/src/typo/lame mkdir /usr/local/src/typo/top mkdir /usr/local/src/typo/bottom Tímto způsobem je možné napsat jenom jeden řádek místo více. Skripty Skript si můžeme představit jako zápis programu který bude vykonávat shell. Jde o sérii příkazů, které jsou interpretovánu stejně jako by bylo v terminálovém okně. Hned na začátku je důležité upomenout, že skript na rozdíl od binárního programu nemůže mít rozdílné GID a UID. Skripty mohou být prováděné jenom s právy na čtení, read (r) a to za pomoci příkazu bash nebo za pomoci.. Pokud by se skript jmenoval skript12 tak by zápis příkazu pro spuštění ve vnořeném shellu následovný: bash skript12. skript12 Pokud budeme chtít, aby skript byl spouštěn i správy na čtení a spuštění (r,x) tak bude spouštěn buď za pomoci pouhého napsání jeho jména (v případe že je v systémových cestách zapsána adresářová struktura kde se nachází daný skript) nebo za pomoci uvedení cesty k souboru skriptu. Ku příkladu:
skript12./skript12 Obsah skriptu Na začátku skriptu musí být vždy napsáno jaký interpret se má spustit. Toto je zaručeno a nastaveno za pomoci prvního řádku souboru, kde by se měla nacházet dvojice znaků #! a za ní cesta k danému interpretu (shellu). Jakékoliv další řádky shellu jsou jenom zápisy spustitelných souboru a dalších shellu jako v příkazové řádce. Ukázka shellu, který vypisuje na standardní výstup (běžně obrazovka terminálu) text Ahoj to jsem ja. #!/bin/bash echo Ahoj to jsem ja Proměnné Systém UNIX dovoluje zapisovat proměnné, jako v programovacích jazycích. Proměnné v systému UNIX jsou však čistě textové. Pro přiřazení proměnné danou hodnotu je používán zápis. jméno_proměnné = [hodnota] Danou proměnnou můžeme potom libovolně používat během daného shellu a to tak, že před jméno proměnné napíšeme symbol $. Příklad: $jméno_proměnné TEMPADRESAR = /dev/boot/temp ls $TEMPADRESAR mkdir $TEMADRESAR/projekt1 Tato série příkazů vytvoří proměnnou TEMPADRESAR která je potom použita na výpis příkazu ls v adresáři /dev/boot/temp a nakonec pro vytvoření adresáře projekt1 v adresáři /dev/boot/temp. Výpis všech aktuálně nastavených proměnných je možné vypsat za pomoci příkazu printenv.
Parametry Vzhledem k tomu, že téměř všechny příkazy v systému UNIX používají parametry tak i skripty jsou schopny tyto parametry načítat a je možno skripty pouštět s parametry. Všechny parametry jsou do skriptu automaticky uloženy jako lokální proměnné a mají názvy 1, 2, 3, 4,.... Pokud chci například vypsat na standardní výstup text Opacne: a pak nejdříve druhý parametr a potom první parametr, tak bude skript vypadat následovně: #!/bin/bash echo Opacne: $2 $1 Pokud spustíme skript který je zde napsán následovně: skript Smile Camera Tak bude výstup vypadat takto: Opacne: Camera Smile