Roura (Unix)

v informatice propojení vstupů a výstupů více příkazů na příkazovém řádku v unixovém shellu

Unixová roura (anglicky pipeline) je jednoduše použitelným prostředkem pro propojení výstupu jednoho procesu (spuštěného programu) se vstupem druhého. Lze například propojit výstup příkazu ls -l s příkazem grep, který propustí pouze řádky začínající znakem d, takže zůstanou informace o podadresářích aktuálního adresáře:

Schematické znázornění propojení standardních proudů anonymními rourami; kolona je zastřešena textovým terminálem
$ ls -l | grep ^d

Použití nepojmenované (anonymní) roury (Unix poskytuje také pojmenované roury) doplňuje možnost přesměrování standardních proudů do nebo ze souboru, jehož jméno stanovuje uživatel až v okamžiku zadání příkazu, o velmi mocný prostředek, který zároveň zpřístupňuje multitasking.

Do kolony propojit i více než dva procesy a tak vytvářet nové vlastnosti:

$ man cp | tr -cs '[:alnum:]' '\n' | sort | uniq -c | sort -rn | less

(příkaz zobrazuje po jednotlivých obrazovkách počty výskytů jednotlivých slovních tvarů v manuálové stránce příkazu cp setříděné od slov s nejvyšším počtem výskytů).

Unixové roury jsou nápaditou formou a implementací staršího konceptu softwarových rour, která byla s určitými omezeními převzata do dalších operačních systémů (DOS, Microsoft Windows, OpenVMS).

Implementace editovat

Softwarové roury jsou rozhraním nebo datovým kanálem mezi dvěma entitami zpracovávajícími data (programy, vlákny, koprogramy atd.), jenž komunikaci zajišťuje v jednom směru a funguje v režimu fronty[1]. Unixová roura, tak jako jiné softwarové roury, představuje pohodlný prostředek realizace přesměrování dat z výstupu jedné entity zpracovávající data na vstup jiné.

Od svých mladších derivátů se unixová roura nejvýrazněji odlišuje tím, že je s ní neodmyslitelně spojeno použití vyrovnávací paměti (bufferu), díky čemuž tato vedle bezobslužného a bezúdržbového postupování dat mezi programy[2], jež další typy roury převzaly především, nabízí také výkonovou optimalizaci, tedy navýšení objemu dat, který kolonou – skupinou procesů zřetězených rourami – proteče za jednotku času.[3]

Unixové roury se dělí na anonymní a pojmenované; anonymní jsou starší než pojmenované a nazývají se též nepojmenované, konvenční nebo tradiční. Pojednává-li se o rouře, aniž by tato byla rozvita přívlastkem, a je-li z kontextu zřejmé, že řeč je o rouře unixové, je s vysokou pravděpodobností myšlena anonymní (unixová) roura.

Roura je (v unixových systémech všeobecně) implementována jako kruhový buffer o celkové velikosti 64 KiB, který je po 4 KiB rozdělený na šestnáct jednotek. Čtení a zápis do roury jsou vybaveny synchronizací, která proces tzv. zablokuje v případě, kdy není co číst, resp. kam zapisovat.

Velmi těsné propojení rour se souborovým systémemunixové systémy se každou entitu snaží abstrahovat jako soubor, nebo jako proces – do roury umožňuje zapisovat a z ní číst těmi systémovými voláními, jimiž se provádí zápis do souboru a čtení z něj.

Nápadný rozdíl oproti práci se soubory spočívá v tom, že anonymní roura má oddělený souborový deskriptor pro zápis od souborového deskriptoru pro čtení – s anonymní rourou jsou propojeny souborové deskriptory dva. Příčinu této odlišnosti lze s úspěchem hledat v tom, že zatímco se souborem lze plnohodnotně pracovat prováděním jen čtení nebo jen zápisu, upotřebení anonymní roury má smysl jen tehdy, když se čte i zapisuje (k datům by se později nebylo možné dostat, jelikož by se na ně nebylo jak odkázat).

Další vlastností, jež práci s rourami odlišuje od práce se soubory, je fakt, že s rourou se zachází jako se zařízením znakovým, zatímco se souborem jako se zařízením blokovým. V důsledku to znamená, že zápis do roury nelze opravit či aktualizovat (jednou předaná data přepsat) a data přečtená z roury přečíst znova (již byla odebrána).

Anonymní roura editovat

Anonymní roury nemají vlastní identifikátor; přístupné jsou toliko prostřednictvím souborových deskriptorů, pročež je možné je využít jen ke komunikaci mezi procesy, které jsou (přímými nebo nepřímými) potomky procesu, jenž je vytvořil, a tímto procesem (mezi libovolnou dvojicí procesů z této množiny) – jiným způsobem, než skrze vytvoření potomka (systémové volání fork[4]), totiž systémovým voláním vytvářejícím anonymní rouru (pipe[5]) získané souborové deskriptory mezi procesy nelze distribuovat.

K anonymním rourám se váže znak svislé čáry („|“) – právě jím uživatel shellu sděluje, že má zájem o použití anonymní roury; po levé a pravé straně se potom nacházejí názvy a parametrizace programů, jež k rouře mají přistupovat – nalevo je jmenována entita do roury data vkládající a napravo entita z roury data odebírající. Proces shellu přitom plní roli rodičovského procesu, mezi nímž a jehož potomky je komunikace anonymní rourou možná pouze, který žádá o vytvoření procesů za účelem vykonání programů v koloně podle předpisu uživatele; součástí jeho agendy je připojení standardního výstupu do roury zapisujícího programu na souborový deskriptor roury pro zápis a svázání standardního vstupu z roury čtecího programu se souborovým deskriptorem roury pro čtení.

S anonymními rourami se pojí taktéž výraz skupina procesů. Procesy participující v koloně patří do téže skupiny procesů, aby celou kolonu bylo možné snadněji spravovat, kupř. stanovovat priority pro plánování na procesor; v rámci skupiny procesů operační systém rovněž může hledat tzv. úzká hrdla, a právě je co do priority s výhledem optimalizace výkonu celé kolony v přidělování procesorového času zvýhodnit.

Jednoduchý příklad editovat

$ history | grep "^java " | wc -l

Příkaz vypíše, kolikrát (za sledovanou historii – např. posledních 500 příkazů) uživatel spustil program java; předpokládá se, že všechna spuštění proběhla se slovem java na začátku příkazu[6].

Program grep v toku potlačuje řádky, které nevyhovují specifikovanému regulárnímu výrazu; mezera na konci vyhledávaného řetězce je začleněna proto, aby z proudu byla vyňata volání programů, jejichž názvy řetězcem java pouze začínají (do této skupiny spadá kupř. primární kompilátor jazyka Java – program javac), znak stříšky udává, že shoda může být uznána pouze tehdy, dojde-li k ní na začátku posuzovaného řetězce.

Program wc s přepínačem -l celý text (všechny jeho řádky) nahrazuje jedním celým číslem, odpovídajícím počtu řádků přijatých na standardním vstupu.

Další jednoduchý příklad editovat

Níže uvedený příkaz demonstruje typické použití programu less, jenž byl pro nasazení na konci kolony anonymních rour přímo navržen. Náplní jeho práce je v textu ze standardního vstupu umožnit listovat (scrollovat), aby uživatel (bez použití složitějších nástrojů) byl schopen přečíst tu úvodní část výstupu, která se nevejde na obrazovku, i v těch textových shellech, jež nedisponují posuvníkem a dostatečnou pamětí.[7] Program less je následovníkem programu more, který dovoluje zachytit celý výstup, ale ne se po odstránkování vracet. V kontextu kolony je less zajímavý tím, že pro to, aby mohl začít řádně fungovat, vyžaduje ukončení toku do něj vstupujících dat (uzavření souborového deskriptoru roury pro zápis).

$ ls -l | less

Program ls provádí výpis obsahu aktuálního adresáře (na standardní výstup).

Složitější příklad editovat

$ wget -q -O '-' 'http://en.wikipedia.org/wiki/Pipeline_(Unix)' | \
sed 's/[^a-zA-Z ]/ /g' | \
tr 'A-Z ' 'a-z\n' | \
grep '[a-z]' | \
sort -u | \
comm -2 -3 '-' '/usr/share/dict/words'

Zadání směřuje k odhalení překlepů na webové stránce, specifikované URL. Následuje popis jednotlivých částí příkazu:

  1. wget z adresy http://en.wikipedia.org/wiki/Pipeline_(Unix) stáhne hypertextový dokument a zapíše jej (přepínač -O) na standardní vstup (parametr -); přepínač -q potlačí výstup běhových informací, implicitně předávaný na standardní chybový výstup.
  2. sed všechny znaky, které nejsou písmenem anglické abecedy nebo mezerou, nahradí mezerou.
  3. tr převede všechna velká písmena na malá a všechny mezery na znak konce řádku. Každé „slovo“ (posloupnost znaků anglické abecedy) tedy bude na samostatném řádku.
  4. grep z proudu odstraní řádky, které neobsahují žádné písmeno anglické abecedy.
  5. sort z toku vyjme všechny duplicitní řádky (přepínač -u) a ponechané abecedně setřídí.
  6. comm text upraví takovým způsobem, že výstup bude roven rozdílu[8] množiny standardního vstupu (parametr -) a množiny souboru /usr/dict/words[9], kde prvky množin tvoří jednotlivé řádky (přepínač -2 z proudu vyloučí řádky obsažené výhradně ve druhém jmenovaném souboru, přepínač -3 tok zbaví řádků vyskytujících se v obou souborech).[10]

Znak zpětného lomítka („\“) bezprostředně předcházející odřádkování interpretu příkazů sděluje, že zadání příkazu nebylo ukončeno (jen se, kvůli přehlednosti, ve formulaci jeho další části pokračuje na následujícím řádku; odřádkování je kromě postoupení příkazu ke zpracování také funkce klávesy ↵ Enter).

Historie editovat

S koncepcí anonymní unixové roury, jež byla poprvé popsána v manuálových stránkách Unixu verze 3, přišel Douglas McIlroy; již první návrh obsahoval znak svislé čáry. První implementaci provedl Ken Thompson v r. 1973, a to do unixového shellu Thompson shell.[11]

Později bylo schéma převzato do dalších operačních systémů, např. AmigaOS, BeOS, Mac OS X[12], MS-DOSu, OpenVMS, OS/2 nebo Windows, a stalo se návrhovým vzorem roury a filtry.

Pojmenovaná roura editovat

Podrobnější informace naleznete v článku Pojmenovaná roura.

Pojmenované roury jsou řešením meziprocesové komunikace, které má prvky předávání dat anonymní rourou i vlastnosti provádění téže činnosti cestou řádných souborů – pojmenované roury jsou globálně adresovatelné (mají v celém systému unikátní identifikátor), a jejich jména je třeba spolupracujícím procesům předávat, ale není nutné se starat, aby pokus o uložení dat do nich neselhal z důvodu nedostatku volného místa na diskové jednotce, a úložiště (nikoli ve smyslu řádného čtení) vyprazdňovat. Vznik a zánik pojmenované roury není vázán životním cyklem kteréhokoli procesu, který z ní může číst, nebo do ní zapisovat; probíhá zcela nezávisle. Jako položka v souborovém systému pojmenovaná roura podléhá koncepci přístupových práv.

Pojmenované roury jsou vhodné pro jiné úlohy, než roury anonymní.

Odkazy editovat

Reference editovat

  1. Charakteristickým rysem fronty je, že odběratel data přebírá v tom pořadí, ve kterém je zdroj vložil.
  2. Starší způsob předávání dat mezi programy – ukládání průběžných dat v souborech – v porovnání s anonymní rourou obsluhu zatěžuje vedlejšími úkony, kupř. pojmenováváním souborů, informováním entit zpracovávajících data o těchto názvech, sledováním, zda pro soubory bude stačit paměť, a jejich vyprázdňováním, popř. mazáním.
  3. Použití vyrovnávací paměti (bufferu) jisté optimalizační účinky unixové roury garantuje i v prostředích, kde není možný současný (paralelní) běh více programů, což by se pro využití potenciálu tzv. bufferování mohlo zdát nezbytné – procesorový čas se ušetří menším objemem synchronizací.
  4. http://linux.die.net/man/2/fork – vytvoření procesu potomka
  5. http://linux.die.net/man/2/pipe – vytvoření anonymní roury
  6. Program java je možné spustit také zápisem /usr/bin/java (na některých distribucích může být umístění programu jiné).
  7. Program less se používá uvnitř programů, které s většími objemy textu pracují nativně (např. man nebo info).
  8. Rozdíl množin A a B je množina všech prvků množiny A, jež nejsou prvky množiny B.
  9. Na některých systémech je databáze slov v souboru /usr/share/dict/words.
  10. Program comm oba vstupní soubory očekává seřazené.
  11. http://www.linfo.org/pipe.html Pipes: A Brief Introduction by The Linux Information Project (LINFO)
  12. Ikona robota [[Automator (software)|]] v operačním systému Mac OS X firmy Apple drží rouru.

Související články editovat

Externí odkazy editovat