<(cmd)
je ksh
funkce se dnes také nachází v zsh
a bash
s názvem náhrada procesu .
Na systémech, které podporují /dev/fd/n
nebo /proc/self/fd/n
, je implementován s rourami, a když ne, s dočasnými pojmenovanými rourami. V každém případě je to forma roury, která je meziprocesovým komunikačním mechanismem.
cmd1 <(cmd2)
Lze zapsat (normálními rourami):
{ cmd2 4<&- | 3<&0 <&4 4<&- cmd1 /dev/fd/3; } 4<&0
Nebo (s pojmenovanými kanály):
mkfifo /tmp/named_pipe
cmd2 > /tmp/named_pipe & cmd1 /tmp/named_pipe
To znamená, že oba příkazy jsou spuštěny současně a komunikují s roura. Obvykle byste použili cmd2 | cmd1
pro to, ale substituce procesu jsou typicky pro ty případy, kde cmd1
může převzít vstup pouze z názvu souboru a ne ze standardního vstupu nebo když je potřeba více než jeden vstup, jako v diff <(cmd1) <(cmd2)
.
Neexistuje žádný rlimit, který to ovlivňuje kromě obecných omezení, jako je počet procesů, čas procesoru nebo paměť.
PIPEBUF hlášené některými implementacemi ulimit
jako bash
a některé implementace ksh
není rlimit, ale maximální velikost, pro kterou je zaručeno, že zápis do roury bude atomický, takže je zde irelevantní. Velikost samotné roury (64 kB na Linuxu, jak uvádí @dsmsk80) není ve skutečnosti sama o sobě limitem. Říká to jen tolik cmd2
může zapisovat do roury i po cmd1
přestal z něj číst.
V tom cmd1
je však omezení může pouze číst z toho souboru. Protože je to roura, nemůže zapisovat do tohoto souboru ani hledat v souboru tam a zpět.
zsh
má třetí formu substituce příkazů pomocí běžných dočasných souborů:
cmd1 =(cmd2)
volání cmd1
s dočasným souborem, který obsahuje výstup cmd2
. V tom případě cmd1
je spuštěn po cmd2 místo souběžně. Tam může být dosaženo limitu velikosti souborů.
Neznám žádný shell implementující <<<(...)
operátor. Existuje však <<<
operátor v zsh
(inspirováno stejným operátorem v unixovém portu rc
) také nalezený v posledních verzích ksh93
a bash
. Je to variace na <<
operátor heredoc s názvem herestring.
V:
cmd <<< something
Což je stejné jako standard:
cmd << EOF
something
EOF
Shell vytvoří dočasný soubor s something\n
jako obsah a zdroje, které jako standardní vstup do nového procesu odpojí tento soubor a spustí cmd
v tom novém procesu. Opět se jedná o běžný soubor, takže lze dosáhnout rlimitu maximální velikosti souboru.
Nyní můžete kombinovat <<<
operátor s $(...)
(náhrada příkazu), aby nějak emuloval zsh
's =(...)
operátor v bash
a ksh93
:
cmd1 <<<"$(cmd2)"
Spustí se cmd2
s ním stdout přesměrován na potrubí. Na druhém konci roury shell čte výstup cmd2
a uloží jej mínus koncové znaky nového řádku a jeden znak nového řádku přidaný do dočasného souboru a volání cmd1
s tímto dočasným souborem otevřeným pro čtení jako stdin (všimněte si, že existuje další omezení v tom, že nebude fungovat, pokud cmd2
výstup obsahuje znaky NUL).
Být jako =(...)
, museli byste to napsat:
cmd1 /dev/fd/3 3<<<"$(cmd3)"
Všimněte si, že shell musí přečíst celý výstup cmd3 v paměti, než jej zapíše do dočasného souboru, takže kromě maximální velikosti souboru můžete také dosáhnout limitu využití paměti.
Všimněte si také, že od verze 5 bash
odebere oprávnění k zápisu do dočasného souboru před voláním cmd1
, takže pokud potřebujete cmd1
abyste mohli tento soubor upravit, museli byste to obejít pomocí:
{
chmod u+w /dev/fd/3 && # only needed in bash 5+
cmd1 /dev/fd/3
} 3<<<"$(cmd3)"
Náhrada procesu Bash ve tvaru <(cmd)
a >(cmd)
je implementován s pojmenovanými kanály, pokud je systém podporuje. Příkaz cmd
je provozován se svým vstupem/výstupem připojeným k potrubí. Když spustíte např. cat <(sleep 10; ls)
vytvořenou rouru najdete v adresáři /proc/pid_of_cat/fd
. Tento pojmenovaný kanál je pak předán jako argument aktuálnímu příkazu (cat
).
Kapacitu vyrovnávací paměti potrubí lze odhadnout pomocí složitého použití dd
příkaz, který odešle nulová data na standardní vstup sleep
příkaz (který nic nedělá). Zdá se, že proces bude nějakou dobu spát, takže se vyrovnávací paměť zaplní:
(dd if=/dev/zero bs=1 | sleep 999) &
Dej tomu chvilku a pak odešleš USR1
signál na dd
proces:
pkill -USR1 dd
Díky tomu je proces tisku statistik I/O:
65537+0 records in
65536+0 records out
65536 bytes (66 kB) copied, 8.62622 s, 7.6 kB/s
V mém testovacím případě je velikost vyrovnávací paměti 64kB
(65536B
).
Jak používáte <<<(cmd)
rozšíření? Jsem si vědom, že se jedná o variaci zde uvedených dokumentů, která je rozšířena a předána příkazu na jeho standardním vstupu.
Doufám, že jsem trochu osvětlil otázku ohledně velikosti. Pokud jde o rychlost, nejsem si tak jistý, ale předpokládal bych, že obě metody mohou poskytnout podobnou propustnost.