È possibile reindirizzare l'output di un comando in più di un comando?


21

Per quanto ne so, posso usare il comando tee per dividere l'output standard sullo schermo e altri file:

command -option1 -option2 argument | tee file1 file2 file3 

È possibile reindirizzare l'output ai comandi anziché ai file utilizzando tee, in modo da poter teoricamente creare una catena di comandi?


3
Spiega cosa intendi per "segnale di uscita" e descrivi cosa intendi per creazione di una "rete di comandi".
Janis,

in Linux ogni comando ha un input e due output. sono etichettati con 0 (per input), 1 (per output) e 2 (per output di errore). Stavo pensando a 1 quando ho detto "segnale di uscita" perché ho letto che il comando tee divide solo l'output etichettato 1. Quando ho detto "rete di comandi" non ero molto tecnico, non sono sicuro di come la rete sia definita correttamente da un punto di vista matematico, ma stavo semplicemente pensando a un albero di comandi tipologicamente parlando, in modo che alcuni comandi possano essere genitori di più di un comando figlio.
Abdul Al Hazred

Grazie per il chiarimento. Per favore, non usare la parola segnale poiché ha un significato specifico in Unix, e il termine era molto fuorviante in questo contesto. Grazie ancora.
Janis,

Alla riga di comando, immettere man -k signal per apprendere il significato speciale di questo concetto chiave in UNIX e Linux. man kill sarebbe una buona pagina per iniziare.
Rob

Inoltre, molte persone si riferiscono a stdin stdout e stderr come "flussi" di input o output. Ci sono piccoli fiumi di dati, quindi un flusso. Avevi ragione a cercare una parola per descriverli collettivamente, ma il segnale è la parola sbagliata.
Rob

Risposte:


25

È possibile utilizzare le named pipe ( http://linux.die.net/man/1/mkfifo ) nella riga di comando di teee fare in modo che i comandi leggano sulle named pipe.

mkfifo /tmp/data0 /tmp/data1 /tmp/data2
cmd0 < /tmp/data0 & cmd1 < /tmp/data1 & cmd2 < /tmp/data2 &
command -option1 -option2 argument | tee /tmp/data0 /tmp/data1 /tmp/data2

Al commandtermine, teechiuderà le pipe nominate, che segnaleranno un EOF (letto di 0 byte) su ciascuno dei /tmp/dataNquali normalmente terminerebbe i cmdNprocessi. Vero esempio:

$ mkfifo /tmp/data0 /tmp/data1 /tmp/data2
$ wc -l < /tmp/data0 & wc -w < /tmp/data1 & wc -c < /tmp/data2 &
$ tee /tmp/data0 /tmp/data1 /tmp/data2 < /etc/passwd >/dev/null
$ 61
1974
37

A causa dei processi in background, la shell ha restituito un prompt prima dell'output del programma. Tutte e tre le istanze sono wcterminate normalmente.


1
In bash , puoi tranquillamente scrivere molto via /tmp/data/{0,1,2}. Poi di nuovo, in bash potresti usare la sostituzione di processo e saltare mkfifocompletamente
Tobias Kienzler

2
Potrebbe voler cambiare / dev / data0 in / tmp / data0. Inoltre, grazie per aver risposto alla domanda in modo agnostico. È più utile che supporre che tutti stiano usando bash.
abonet

15

Se ho capito bene, si sta guardando per l'equivalente di tee file1 file2 file3, ma invece di scrivere gli stessi dati a tre file file1, file2e file3, si vuole tubo gli stessi dati in tre comandi cmd1, cmd2e cmd3, cioè

… | ??? cmd1 cmd2 cmd3

dovrebbe essere equivalente a

… | cmd1 &
… | cmd2 &
… | cmd3 &

tranne che sarebbe eseguito solo una volta.

Ci sono due modi per farlo.

Ksh93, bash e zsh supportano la sostituzione del processo . Questa è una generalizzazione di pipe che consente all'argomento di un comando di essere un file che, quando scritto, passa i dati come input a un comando (esiste anche la variante di input che, quando viene letta, ottiene l'output di dati da un comando) . Questo è,

echo hello | tee >(cmd1)

stampe hellostandard output e in aggiunta corre cmd1con hellocome input.

Ad esempio, se si desidera duplicare l'input di somecommande passarlo a entrambi cmd1e cmd2, è possibile utilizzare

somecommand | tee >(cmd1) | cmd2

Se la shell non supporta la sostituzione dei processi, è possibile utilizzare invece named pipe. Vedi la risposta di Arcege per come funziona. Le pipe nominate sono meno convenienti della sostituzione del processo perché è necessario crearle ed eliminarle, nonché avviare e sincronizzare i processi manualmente. Hanno il vantaggio di essere completamente portatili, mentre non tutte le shell supportano le sostituzioni di processo. Possono anche essere utilizzati in scenari diversi da quelli previsti per la sostituzione del processo.

Sotto il cofano, su alcuni sistemi, la sostituzione del processo utilizza internamente pipe denominate. Sulla maggior parte dei sistemi, tuttavia, si basa su file denominati che rappresentano descrittori di file .


5
Vedi anche peeda moreutils.
Stéphane Chazelas,

Nota che la sostituzione del processo è stata introdotta da ksh88.
Stéphane Chazelas,

6

Almeno in puoi saltare mkfifousando la sostituzione del processo:

command -option1 -option2 argument | tee >(cmd1) >(cmd2) >(cmd3)

o per adottare l'esempio di Arcege

tee >(wc -l) >(wc -w) >(wc -c) < /etc/passwd >/dev/null

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.