Nikdy jsem ve skutečnosti nepřemýšlel o tom, jak shell skutečně provádí rourkované příkazy. Vždy mi říkali, že „stdout jednoho programu se provádí do stdin jiného“, jako způsob uvažování o potrubí. Přirozeně jsem si myslel, že v případě řekněme A | B
, A
se spustí jako první, potom B
získá stdout z A
a používá stdout z A
jako jeho vstup.
Ale všiml jsem si, že když lidé hledají konkrétní proces v ps
, budou zahrnovat grep -v "grep"
na konci příkazu, abyste se ujistili, že grep
se neobjeví v konečném výstupu.
To znamená, že v příkazu ps aux | grep "bash" | grep -v "grep"
předpokládá se, že ps
věděl, že grep
byl spuštěn, a proto je ve výstupu ps
. Ale pokud ps
dokončí běh, než se jeho výstup přenese do grep
, jak to vědělo, že grep
běžel?
[email protected]: ~$ ps | grep ".*"
PID TTY TIME CMD
3773 pts/0 00:00:00 bash
3784 pts/0 00:00:00 ps
3785 pts/0 00:00:00 grep
Přijatá odpověď:
Propojené příkazy běží souběžně. Když spustíte ps | grep …
, je to štěstí při losování (nebo otázka detailů fungování shellu v kombinaci s doladěním plánovače hluboko v útrobách jádra), zda ps
nebo grep
se spouští jako první a v každém případě pokračují v souběžném provádění.
To se velmi běžně používá k tomu, aby druhý program mohl zpracovávat data tak, jak vycházejí z prvního programu, než první program dokončí svou činnost. Například
grep pattern very-large-file | tr a-z A-Z
začne zobrazovat odpovídající řádky velkými písmeny ještě před grep
dokončil procházení velkého souboru.
grep pattern very-large-file | head -n 1
zobrazí první odpovídající řádek a může se zastavit zpracování dlouho před grep
dokončil čtení svého vstupního souboru.
Pokud se někde dočtete, že programy z potrubí běží postupně, opusťte tento dokument. Propojené programy běží souběžně a vždy běží.