GNU/Linux >> Znalost Linux >  >> Linux

Vytvoření dočasného souboru vs substituce procesu vs expanze proměnné?

<(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.


Linux
  1. Průvodce pro začátečníky vytvářením přesměrování v souboru .htaccess

  2. Jak zjistit, který proces vytváří soubor?

  3. Jak odložit variabilní expanzi?

  1. Výstup procesní substituce je mimo provoz?

  2. Substituce proměnné prostředí v sed

  3. Vyloučení adresáře při vytváření souboru .tar.gz

  1. Filtrování tcpdump:Vytváření řádu z chaosu

  2. variabilní dostupnost prostředí v Linuxu

  3. Zjistěte, který proces upravuje soubor