Soluzione 1:
Personalmente, il mio preferito (richiede bash e altre cose che sono standard nella maggior parte delle distribuzioni Linux)
I dettagli possono dipendere molto dall'output delle due cose e da come vuoi unirle...
Contenuti di command1 e command2 uno dopo l'altro nell'output:
cat <(command1) <(command2) > outputfile
O se entrambi i comandi restituiscono versioni alternative degli stessi dati che vuoi vedere fianco a fianco (l'ho usato con snmpwalk; numeri su un lato e nomi MIB sull'altro):
paste <(command1) <(command2) > outputfile
O se vuoi confrontare l'output di due comandi simili (diciamo una ricerca su due directory diverse)
diff <(command1) <(command2) > outputfile
Oppure, se sono output ordinati di qualche tipo, uniscili:
sort -m <(command1) <(command2) > outputfile
Oppure esegui entrambi i comandi contemporaneamente (potrebbe confondere un po' le cose, però):
cat <(command1 & command2) > outputfile
L'operatore <() imposta una named pipe (o /dev/fd) per ogni comando, inviando l'output di quel comando alla named pipe (o riferimento al filehandle /dev/fd) e passa il nome sulla riga di comando. C'è un equivalente con>(). Potresti fare:command0 | tee >(command1) >(command2) >(command3) | command4
per inviare simultaneamente l'output di un comando ad altri 4 comandi, ad esempio.
Soluzione 2:
Puoi aggiungere due stream a un altro con cat
, come mostra il gorilla.
Puoi anche creare un FIFO, indirizzare l'output dei comandi a quello, quindi leggere dal FIFO con qualsiasi altro programma:
mkfifo ~/my_fifo
command1 > ~/my_fifo &
command2 > ~/my_fifo &
command3 < ~/my_fifo
Particolarmente utile per i programmi che scrivono o leggono solo un file o che mescolano programmi che emettono solo stdout/file con uno che supporta solo l'altro.
Soluzione 3:
(tail -f /tmp/p1 & tail -f /tmp/p2 ) | cat > /tmp/output
/tmp/p1
e /tmp/p2
sono le pipe di input, mentre /tmp/output
è l'output.
Soluzione 4:
Ho creato un programma speciale per questo:fdlinecombine
Legge più pipe (di solito output del programma) e le scrive in stdout linewise (puoi anche sovrascrivere il separatore)
Soluzione 5:
Stai attento qui; solo catturarli finirà per mescolare i risultati in modi che potresti non volere:ad esempio, se sono file di registro probabilmente non vuoi davvero che una riga di uno venga inserita a metà di una riga dell'altro. Se va bene, allora
tail -f /tmp/p1 /tmp/p2>/tmp/output
funzionerà. Se non è ok, allora dovrai trovare qualcosa che faccia il line buffering e produca solo righe complete. Syslog fa questo, ma non sono sicuro di cos'altro potrebbe.
EDIT:ottimizzazione per lettura senza buffer e named pipe:
considerando /tmp/p1 , /tmp/p2 , /tmp/p3 come named pipe, create da "mkfifo /tmp/pN "
tail -q -f /tmp/p1 /tmp/p2 | awk '{print $0> "/tmp/p3"; chiudi("/tmp/p3"); fflush();}' &
ora in questo modo possiamo leggere l'Output named pipe "/tmp/p3" unbuffered di :
tail -f /tmp/p3
c'è un piccolo bug di sorta, devi "inizializzare" la prima pipe di input /tmp/p1 da:
echo -n> /tmp/p1
per seguire accetterà prima l'input dalla seconda pipe /tmp/p2 e non aspetterà fino a quando arriva qualcosa a /tmp/p1 . questo potrebbe non essere il caso, se sei sicuro, /tmp/p1 riceverà l'input per primo.
Anche l'opzione -q è necessaria per tail non stampa spazzatura sui nomi dei file.