<(cmd)
è un ksh
caratteristica che si trova oggi anche in zsh
e bash
chiamata sostituzione del processo .
Sui sistemi che supportano /dev/fd/n
o /proc/self/fd/n
, viene implementato con pipe e, quando non lo è, con pipe denominate temporanee. In ogni caso, è una forma di pipe che è un meccanismo di comunicazione tra processi.
cmd1 <(cmd2)
Può essere scritto (con pipe normali):
{ cmd2 4<&- | 3<&0 <&4 4<&- cmd1 /dev/fd/3; } 4<&0
Oppure (con named pipe):
mkfifo /tmp/named_pipe
cmd2 > /tmp/named_pipe & cmd1 /tmp/named_pipe
Cioè, entrambi i comandi vengono avviati contemporaneamente e comunicano con una pipe. Di solito useresti cmd2 | cmd1
per questo, ma la sostituzione del processo è in genere per quei casi in cui cmd1
può solo prendere input da un nome file e non da input standard o quando è necessario più di un input come in diff <(cmd1) <(cmd2)
.
Non ci sono limiti che lo influenzano se non quelli generali come il numero di processi, il tempo della CPU o la memoria.
Il PIPEBUF riportato da alcune implementazioni di ulimit
come bash
e alcune implementazioni di ksh
non è un rlimit ma la dimensione massima per la quale è garantito che una scrittura su una pipe sia atomica, quindi qui è irrilevante. La dimensione della pipe stessa (64kB su Linux come riportato da @dsmsk80) non è realmente un limite in sé. Dice solo che è tanto cmd2
può scrivere nella pipe anche dopo cmd1
ha smesso di leggerlo.
C'è una limitazione però in quel cmd1
può solo leggere da quel fascicolo. Poiché è una pipe, non può scrivere su quel file o cercare avanti e indietro nel file.
zsh
ha una terza forma di sostituzione dei comandi che utilizza normali file temporanei:
cmd1 =(cmd2)
chiama cmd1
con un file temporaneo che contiene l'output di cmd2
. In tal caso cmd1
viene eseguito dopo cmd2 invece che contemporaneamente. Il limite sulla dimensione dei file può essere raggiunto lì.
Non conosco nessuna shell che implementi un <<<(...)
operatore. C'è comunque un <<<
operatore in zsh
(ispirato dallo stesso operatore nel port Unix di rc
) trovato anche nelle versioni recenti di ksh93
e bash
. È una variante del <<
Operatore heredoc chiamato herestring.
In:
cmd <<< something
Che è lo stesso dello standard:
cmd << EOF
something
EOF
La shell crea un file temporaneo con something\n
come contenuto e feed che come input standard per un nuovo processo, scollega quel file ed esegue cmd
in quel nuovo processo. Anche in questo caso, si tratta di un file normale, quindi potrebbe essere raggiunto il limite della dimensione massima di un file.
Ora puoi combinare il <<<
operatore con $(...)
(comando di sostituzione) per emulare in qualche modo zsh
=(...)
di operatore in bash
e ksh93
:
cmd1 <<<"$(cmd2)"
Eseguirebbe cmd2
con esso stdout reindirizzato a una pipe. All'altra estremità della pipe, la shell legge l'output di cmd2
e lo memorizza meno i caratteri di nuova riga finali e con un carattere di nuova riga aggiunto in un file temporaneo e chiama cmd1
con quel file temporaneo aperto per la lettura come stdin (nota che c'è un'altra limitazione in quanto non funzionerà se cmd2
l'output contiene caratteri NUL).
Essere come =(...)
, dovresti scriverlo:
cmd1 /dev/fd/3 3<<<"$(cmd3)"
Nota che la shell deve leggere l'intero output di cmd3 in memoria prima di scriverlo nel file temporaneo, quindi oltre alla dimensione massima del file, potresti anche raggiungere il limite sull'utilizzo della memoria.
Si noti inoltre che dalla versione 5, bash
toglie i permessi di scrittura al file temporaneo prima di chiamare cmd1
, quindi se hai bisogno di cmd1
per poter modificare quel file, dovresti aggirarlo con:
{
chmod u+w /dev/fd/3 && # only needed in bash 5+
cmd1 /dev/fd/3
} 3<<<"$(cmd3)"
Sostituzione del processo Bash sotto forma di <(cmd)
e >(cmd)
è implementato con pipe denominate se il sistema le supporta. Il comando cmd
viene eseguito con il suo ingresso/uscita collegato a una pipe. Quando corri ad es. cat <(sleep 10; ls)
puoi trovare la pipe creata nella directory /proc/pid_of_cat/fd
. Questa pipe denominata viene quindi passata come argomento al comando corrente (cat
).
La capacità del buffer di una pipe può essere stimata con un uso complicato di dd
comando che invia zero dati allo standard input di sleep
comando (che non fa nulla). Apparentemente, il processo dormirà per un po', quindi il buffer si riempirà:
(dd if=/dev/zero bs=1 | sleep 999) &
Aspetta un secondo e poi invia USR1
segnale al dd
processo:
pkill -USR1 dd
Questo rende il processo per stampare le statistiche di I/O:
65537+0 records in
65536+0 records out
65536 bytes (66 kB) copied, 8.62622 s, 7.6 kB/s
Nel mio caso di test, la dimensione del buffer è 64kB
(65536B
).
Come si usa <<<(cmd)
espansione? Sono consapevole che si tratta di una variazione di here documents che viene espansa e passata al comando nel suo input standard.
Spero di aver fatto luce sulla domanda sulle dimensioni. Per quanto riguarda la velocità, non ne sono così sicuro, ma presumo che entrambi i metodi possano fornire un throughput simile.