GNU/Linux >> Linux Esercitazione >  >> Linux

Creazione di file temporanei rispetto alla sostituzione del processo rispetto all'espansione variabile?

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


Linux
  1. Una guida per principianti alla creazione di reindirizzamenti in un file .htaccess

  2. Come determinare quale processo sta creando un file?

  3. Come differire l'espansione variabile?

  4. L'output di sostituzione del processo è fuori servizio?

  5. Creare un file vuoto con un nome di variabile in uno script?

Shell - Scrive contenuti variabili in un file

Riavvia il processo alla modifica del file in Linux

Creazione di un demone in Linux

xauth non crea il file .Xauthority

accessibilità delle variabili d'ambiente in Linux

Scarica la memoria di un processo Linux su file