risposta-alla-domanda-sullo-sviluppo-web-bd.com

Come reindirizzare l'output a un file e stdout

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?

754
SCdF

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
1031
Zoredache
$ 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
459
Matthew Alpert

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

102
tsenapathy

Puoi principalmente usare Zoredachesolution , ma se non vuoi sovrascrivere il file di output dovresti scrivere tee con l'opzione -a come segue:

ls -lR / | tee -a output.file
16
O.Badr

Qualcosa da aggiungere ...

Il pacchetto unbuffer ha problemi di supporto con alcuni pacchetti sotto Fedora e redhat release unix.

Mettendo da parte i problemi 

Dopo aver lavorato per me

bash myscript.sh 2>&1 | tee output.log

Grazie ScDF & matthew I tuoi input mi hanno risparmiato un sacco di tempo ..

11
nitinr708

usare tail -f output dovrebbe funzionare.

6
Chuck Phillips

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.

3
jorfus

< 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" 
0
kiran sai

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 mylogfilename__ e lascia che tutto vada a stdout allo stesso tempo .

Si usano alcuni trucchi stupidi:

  • usa execsenza comando per impostare i reindirizzamenti,
  • usa teeper duplicare le uscite,
  • riavviare lo script con i reindirizzamenti desiderati,
  • usa uno speciale primo parametro (un semplice carattere NULspecificato dalla notazione bash speciale $'string') per specificare che lo script viene riavviato (nessun parametro equivalente può essere usato dal tuo lavoro originale),
  • prova a mantenere lo stato di uscita originale quando si riavvia lo script usando l'opzione pipefailname__.

Brutto ma utile per me in certe situazioni.

0
Bruno BEAUFILS