In bash, chiamando foo
mostrerebbe qualsiasi output da quel comando sullo stdout.
Chiamando foo > output
reindirizzare qualsiasi output da quel comando al file specificato (in questo caso 'output').
C'è un modo per reindirizzare l'output su un file e farlo visualizzare su stdout?
Il comando che vuoi è chiamato tee
:
foo | tee output.file
Ad esempio, se ti interessa solo lo stdout:
ls -a | tee output.file
Se vuoi includere stderr, fai:
program [arguments...] 2>&1 | tee outfile
2>&1
reindirizza il canale 2 (stderr/errore standard) nel canale 1 (stdout/output standard), in modo che entrambi siano scritti come stdout. Viene inoltre indirizzato al file di output specificato come il comando tee
.
Inoltre, se vuoi aggiungere al file di log, usa tee -a
come:
program [arguments...] 2>&1 | tee -a outfile
$ program [arguments...] 2>&1 | tee outfile
2>&1
scarica i flussi stderr e stdout .tee outfile
prende lo stream che riceve e lo scrive sullo schermo e sul file "outfile".
Questo è probabilmente ciò che la maggior parte della gente sta cercando. La situazione probabile è che alcuni programmi o script stiano lavorando per molto tempo e producano molto output. L'utente vuole controllarlo periodicamente per il progresso, ma vuole anche che l'output sia scritto su un file.
Il problema (specialmente quando si mescolano i flussi stdout e stderr) è che si fa affidamento sugli stream che vengono scaricati dal programma. Se, ad esempio, tutte le scritture su stdout sono non svuotate, ma tutte le scritture su stderr sono svuotate, allora finiranno nell'ordine cronologico nel file di output e sullo schermo.
È anche un male se il programma emette solo 1 o 2 righe ogni pochi minuti per segnalare i progressi. In tal caso, se l'output non fosse stato svuotato dal programma, l'utente non avrebbe nemmeno visto alcun output sullo schermo per ore, perché nessuno di questi sarebbe stato spinto attraverso il tubo per ore.
Aggiornamento: Il programma unbuffer
, parte del pacchetto expect
, risolverà il problema del buffering. Ciò farà sì che stdout e stderr scrivano sullo schermo e file immediatamente e li mantengano sincronizzati quando vengono combinati e reindirizzati a tee
. Per esempio.:
$ unbuffer program [arguments...] 2>&1 | tee outfile
Un altro modo per me è,
<command> |& tee <outputFile>
come mostrato in gnu bash manual
Esempio:
ls |& tee files.txt
Se '| &' è usato, l'errore standard di command1, oltre al suo output standard, è collegato allo standard input di command2 attraverso la pipe, è shorthand per 2> & 1 |. Questo reindirizzamento implicito dell'errore standard all'output standard viene eseguito dopo ogni reindirizzamento specificato dal comando.
Per ulteriori informazioni, consultare reindirizzamento
usare tail -f output
dovrebbe funzionare.
Risposta bonus poiché questo caso d'uso mi ha portato qui:
Nel caso in cui è necessario farlo come qualche altro utente
echo "some output" | Sudo -u some_user tee /some/path/some_file
Nota che l'eco avverrà mentre tu e la scrittura del file avverrà come "qualcuno_utente" cosa saràNONlavoro se dovessi eseguire l'eco come "some_user" e reindirizzare l'output con >> "some_file" perché il reindirizzamento del file avverrà come te.
Suggerimento: tee supporta anche append con il flag -a, se è necessario sostituire una riga in un file come un altro utente che potresti eseguire sed come l'utente desiderato.
< command > |& tee filename
# questo creerà un file "nomefile" con lo stato del comando come contenuto, Se un file esiste già rimuoverà il contenuto esistente e scriverà lo stato del comando.
< command > | tee >> filename
# questo aggiungerà lo stato al file ma non stampa lo stato del comando su standard_output (schermo).
Voglio stampare qualcosa usando "echo" sullo schermo e aggiungere i dati eco a un file
echo "hi there, Have to print this on screen and append to a file"
Puoi farlo per l'intero script usando qualcosa di simile all'inizio dello script:
#!/usr/bin/env bash
test x$1 = x$'\x00' && shift || { set -o pipefail ; ( exec 2>&1 ; $0 $'\x00' "[email protected]" ) | tee mylogfile ; exit $? ; }
# do whaetever you want
Questo reindirizza sia gli output stderr che stdout al file chiamato mylogfile
name__ e lascia che tutto vada a stdout allo stesso tempo .
Si usano alcuni trucchi stupidi:
exec
senza comando per impostare i reindirizzamenti,tee
per duplicare le uscite,NUL
specificato dalla notazione bash speciale $'string'
) per specificare che lo script viene riavviato (nessun parametro equivalente può essere usato dal tuo lavoro originale),pipefail
name__.Brutto ma utile per me in certe situazioni.