Come reindirizzare e aggiungere sia stdout che stderr a un file con Bash?


1535

Per reindirizzare stdout su un file troncato in Bash, so usare:

cmd > file.txt

Per reindirizzare stdout in Bash, aggiungendo un file, so di usare:

cmd >> file.txt

Per reindirizzare sia stdout che stderr su un file troncato, so di usare:

cmd &> file.txt

Come reindirizzare sia stdout che stderr accodando a un file? cmd &>> file.txtNon ha funzionato per me.


37
Vorrei sottolineare che &> outfile è un codice specifico di Bash (e altri) e non portatile. Il modo di andare portatile (simile alle risposte allegate) è sempre stato ed è ancora> outfile 2> & 1
TheBonsai,

Risposte:


1999
cmd >>file.txt 2>&1

Bash esegue i reindirizzamenti da sinistra a destra come segue:

  1. >>file.txt: Apri file.txtin modalità append e reindirizza stdoutlì.
  2. 2>&1: Reindirizza stderra "dove stdoutsta andando attualmente" . In questo caso, si tratta di un file aperto in modalità append. In altre parole, &1riutilizza il descrittore di file che stdoutattualmente utilizza.

33
funziona alla grande! ma c'è un modo per dare un senso a questo o dovrei trattarlo come un costrutto atomico bash?
flybywire,

181
È semplice reindirizzamento, le istruzioni di reindirizzamento vengono valutate, come sempre, da sinistra a destra. >> file: rosso. STDOUT al file (modalità append) (abbreviazione di 1 >> file) 2> & 1: rosso. STDERR su "dove va stdout" Notare che l'interpretazione "reindirizzare STDERR su STDOUT" è errata.
TheBonsai,

31
Dice "aggiungi output (stdout, descrittore di file 1) su file.txt e invia stderr (descrittore di file 2) nello stesso posto di fd1".
In pausa fino a nuovo avviso.

2
@TheBonsai tuttavia cosa succede se devo reindirizzare STDERR su un altro file ma accodare? È possibile?
Arod

41
se lo fai cmd >>file1 2>>file2dovrebbe raggiungere quello che vuoi.
Woodrow Douglass,

367

Esistono due modi per farlo, a seconda della versione di Bash.

Il modo classico e portatile ( Bash pre-4 ) è:

cmd >> outfile 2>&1

Un modo non portabile, a partire da Bash 4 è

cmd &>> outfile

(analogico a &> outfile)

Per un buon stile di codifica, dovresti

  • decidere se la portabilità è un problema (quindi utilizzare il modo classico)
  • decidere se la portabilità anche su Bash pre-4 è una preoccupazione (quindi utilizzare il modo classico)
  • non importa quale sintassi usi, non cambiarla all'interno dello stesso script (confusione!)

Se lo script inizia già con #!/bin/sh(indipendentemente dal fatto che sia previsto o meno), la soluzione Bash 4, e in generale qualsiasi codice specifico di Bash, non è la strada da percorrere.

Ricorda inoltre che Bash 4 &>>è solo una sintassi più breve: non introduce nuove funzionalità o qualcosa del genere.

La sintassi è (accanto ad altre sintassi di reindirizzamento) qui descritta: http://bash-hackers.org/wiki/doku.php/syntax/redirection#appending_redirected_output_and_error_output


8
Preferisco & >> poiché è coerente con &> e >>. È anche più facile leggere "aggiungi output ed errori a questo file" piuttosto che "invia errori all'output, aggiungi output a questo file". Nota mentre Linux generalmente ha una versione corrente di bash, OS X, al momento della scrittura, richiede ancora bash 4 per l'installazione manuale tramite homebrew ecc.
mikemaccana,

Mi piace di più perché è più corto e solo tweoi per riga, quindi cosa farebbe ad esempio zsh da "& >>"?
Phillipp,

È anche importante notare che in un processo cron, è necessario utilizzare la sintassi pre-4, anche se il sistema ha Bash 4.
hyperknot

5
@zsero cron non usa affatto bash ... lo usa sh. È possibile modificare la shell predefinita anteponendo SHELL=/bin/bashal crontab -efile.
Ray Foss,

89

In Bash puoi anche specificare esplicitamente i tuoi reindirizzamenti a diversi file:

cmd >log.out 2>log_error.out

L'aggiunta sarebbe:

cmd >>log.out 2>>log_error.out

6
Il reindirizzamento di due flussi sullo stesso file utilizzando la prima opzione farà sì che il primo scriva "in primo piano" del secondo, sovrascrivendo alcuni o tutti i contenuti. Utilizzare invece cmd >> log.out 2> log.out .
Orestis P.

3
Grazie per averlo colto; hai ragione, l'uno ostruirà l'altro. Tuttavia, il tuo comando non funziona neanche. Penso che l'unico modo per scrivere nello stesso file sia come è stato dato prima cmd >log.out 2>&1. Sto modificando la mia risposta per rimuovere il primo esempio.
Aaron R.,

65

In Bash 4 (oltre a ZSH 4.3.11):

cmd &>>outfile

appena fuori dalla scatola


2
@all: questa è una buona risposta, poiché funziona con bash ed è breve, quindi ho modificato per assicurarmi che menzioni esplicitamente bash.
mikemaccana,

10
@mikemaccana: la risposta di TheBonsai mostra la soluzione bash 4 dal 2009
jfs

52

Questo dovrebbe funzionare bene:

your_command 2>&1 | tee -a file.txt

Memorizzerà tutti i log in file.txt e li scaricherà sul terminale.


Questa è la risposta corretta se si desidera vedere anche l'output nel terminale. Tuttavia, questa non era la domanda inizialmente posta.
Mikko Rantalainen,

25

Prova questo

You_command 1>output.log  2>&1

L'utilizzo di &> x.file funziona in bash4. scusa per quella cosa : (

Ecco alcuni suggerimenti aggiuntivi.

0, 1, 2 ... 9 sono descrittori di file in bash.

0 sta per stdin, 1 sta per stdout, 2 sta per stderror. 3 ~ 9 è di riserva per qualsiasi altro utilizzo temporaneo.

Qualsiasi descrittore di file può essere reindirizzato ad altri descrittori o file utilizzando l'operatore >o >>(append).

Utilizzo: < file_descriptor > > < filename | & file_descriptor >

Fare riferimento a http://www.tldp.org/LDP/abs/html/io-redirection.html


Il tuo esempio farà qualcosa di diverso da quello richiesto dall'OP: reindirizzerà lo stderr di You_commanda stdout e lo stdout di You_commandal file output.log. Inoltre, non verrà aggiunto al file ma lo sovrascriverà.
pabouk,

Corretto: il descrittore di file può essere qualsiasi valore superiore a 3 per tutti gli altri file.
Itachi,

5
La tua risposta mostra l'errore di reindirizzamento dell'output più comune: reindirizzare STDERR a dove STDOUT sta puntando attualmente e solo dopo che reindirizza STDOUT su file. Ciò non provocherà il reindirizzamento di STDERR sullo stesso file. L'ordine dei reindirizzamenti è importante.
Jan Wikholm,

1
vuol dire che devo prima reindirizzare STDERROR su STDOUT, quindi reindirizzare STDOUT su un file. 1 > output.log 2>&1
Quintus.Zhou

1
@ Quintus.Zhou Yup. La tua versione reindirizza err su out e allo stesso tempo su file.
Alex Yaroshevich,

11

Sono sorpreso che in quasi dieci anni nessuno abbia ancora pubblicato questo approccio:

Se usi versioni precedenti di bash dove &>>non è disponibile, puoi anche fare:

(cmd 2>&1) >> file.txt

Questo genera una subshell, quindi è meno efficiente dell'approccio tradizionale di cmd >> file.txt 2>&1, e di conseguenza non funzionerà per i comandi che devono modificare la shell corrente (ad esempio cd, pushd), ma questo approccio sembra più naturale e comprensibile per me:

  1. Reindirizza stderr a stdout.
  2. Reindirizzare il nuovo stdout aggiungendo a un file.

Inoltre, le parentesi rimuovono qualsiasi ambiguità dell'ordine, soprattutto se si desidera invece reindirizzare stdout e stderr a un altro comando.


Questa implementazione provoca un ulteriore processo per l'esecuzione del sistema. L'uso della sintassi cmd >> file 2>&1funziona in tutte le shell e non richiede un processo aggiuntivo per l'esecuzione.
Mikko Rantalainen,

@MikkoRantalainen Ho già spiegato che genera una subshell ed è meno efficiente. Il punto di questo approccio è che se l'efficienza non è un grosso problema (e raramente lo è), in questo modo è più facile da ricordare e più difficile sbagliare.
jamesdlin,
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.