V tomto článku prozkoumáme fascinující svět Roura (Unix) a jeho dopad na naše životy. Roura (Unix) byl základní postavou v historii lidstva a hrál zásadní roli v různých aspektech, od vědy a techniky po kulturu a umění. V průběhu let vzbudil Roura (Unix) velký zájem a stal se předmětem studia a výzkumu, odhalující překvapivé aspekty, které změnily náš pohled na svět. V tomto článku budeme analyzovat různé aspekty Roura (Unix) a jeho vliv na lidský rozvoj a nabídneme hluboký a obohacující pohled na toto vzrušující téma.
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:
$ 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 '' '\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).
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émem – unixové 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í 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.
$ 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.
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).
$ wget -q -O '-' 'http://en.wikipedia.orghttps://scientiacs.com/Pipeline_(Unix)' | \
sed 's// /g' | \
tr 'A-Z ' 'a-z\n' | \
grep '' | \
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:
wget
z adresy http://en.wikipedia.orghttps://scientiacs.com/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.sed
všechny znaky, které nejsou písmenem anglické abecedy nebo mezerou, nahradí mezerou.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.grep
z proudu odstraní řádky, které neobsahují žádné písmeno anglické abecedy.sort
z toku vyjme všechny duplicitní řádky (přepínač -u
) a ponechané abecedně setřídí.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).
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é 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í.
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é).
less
se používá uvnitř programů, které s většími objemy textu pracují nativně (např. man
nebo info
).
comm
oba vstupní soubory očekává seřazené.
pipe
od OpenGroup (Single UNIX Specification)fork
od OpenGroup (Single UNIX Specification)mkfifo
– zřízení pojmenované roury