Differenza tra 2> & 1> output.log e 2> & 1 | tee output.log


35

Volevo sapere la differenza tra i seguenti due comandi

2>&1 > output.log 

e

2>&1 | tee output.log

Ho visto uno dei miei colleghi utilizzare la seconda opzione per reindirizzare. So cosa fanno 2> & 1, la mia unica domanda è qual è lo scopo dell'uso di tee dove può essere utilizzato un semplice operatore di reindirizzamento ">"?

Risposte:


11

Guardando i due comandi separatamente:

utility 2>&1 >output.log 

Qui, dal momento che i reindirizzamenti vengono elaborati in modo da sinistra a destra, il flusso di errori standard verrebbe prima reindirizzato verso qualsiasi destinazione del flusso di output standard (possibilmente verso la console), quindi il flusso di output standard verrebbe reindirizzato su un file. Il flusso di errori standard non verrebbe reindirizzato a quel file.

L'effetto visibile di ciò sarebbe che sullo schermo viene visualizzato ciò che viene prodotto sull'errore standard e ciò che viene prodotto sull'output standard nel file.

utility 2>&1 | tee output.log

Qui, reindirizza l'errore standard nella stessa posizione del flusso di output standard. Ciò significa che entrambi i flussi verranno reindirizzati teeall'utilità come un singolo flusso di output mescolato e che questi dati di output standard verranno salvati nel file specificato da tee. I dati verrebbero inoltre riprodotti teenella console (questo è ciò che teefa, duplica flussi di dati).

Quale mai uno di questi viene utilizzato dipende da ciò che ti piacerebbe ottenere.

Si noti che non sarebbe possibile riprodurre l'effetto della seconda pipeline con just >(come in utility >output.log 2>&1, che salverebbe sia l'output standard che l'errore nel file). Dovresti utilizzare teeper ottenere i dati nella console e nel file di output.


Note aggiuntive:

L' effetto visibile del primo comando,

utility 2>&1 >output.log 

sarebbe lo stesso di

utility >output.log

Vale a dire, l'output standard va al file e l'errore standard va alla console.

Se alla fine di ciascuno dei comandi sopra fosse aggiunto un ulteriore passo di elaborazione, ci sarebbe comunque una grande differenza:

utility 2>&1 >output.log | more_stuff

utility >output.log      | more_stuff

Nella prima pipeline, more_stuffquello che originariamente era il flusso di errore standard utilitycome dati di input standard, mentre nella seconda pipeline, poiché è solo il flusso di output standard risultante che viene mai inviato attraverso una pipa, la more_stuffparte della pipeline non otterrebbe nulla leggere sul suo input standard.


Con il comando " utility 2>&1 | tee output.log, intendi dire che poiché 1 viene indirizzato a tee, anche 2 lo è. Poiché tee duplica il flusso, l'output viene visualizzato sia sulla console sia scritto su file? Da qui la differenza tra utility 2>&1 > output.loge utility 2>&1 | tee output.logè teeche duplica il flusso. Sarebbe corretto?
Motivato il

Con gli esempi di utility 2>&1 > output.log | more_stuffe utility >ouput.log| more_stuff , is the difference that more_stuff` ha l'output di errore standard sulla console come input more_stuff? Dal momento che nel secondo esempio, non vi è alcun output per la console, in sostanza non c'è input per more_stuff? In caso affermativo, ciò non è chiaro dal paragrafo precedente, si noti che l'output standard va al file e l'errore standard va alla console.
Motivato il

@Motivato Il tuo primo commento mi sembra corretto, sì. Per quanto riguarda il secondo commento: Nel primo comando, more_stuffriceverebbe ciò che utilityoriginariamente inviato al suo flusso di errori (ma che è stato reindirizzato all'output standard). Non perché finirebbe sulla console se more_stuffnon ci fosse, ma perché andrà al flusso di output standard . Nel secondo comando, nonmore_stuff riceve nulla in quanto non esiste un output standard dal lato sinistro della pipeline. Il flusso di errori da utilityfinirebbe comunque sulla console nel secondo comando.
Kusalananda

Grazie. Vuoi dire che perché il comando utility > output.log | more_stuffnon genera un output nel flusso di output standard da un punto di vista dell'errore standard?
Motivato il

@Motivated Dato che il lato sinistro non produce nulla sull'output standard (viene reindirizzato), nessun dato verrà inviato sul pipe.
Kusalananda

24

Nota editoriale

Assicurati di leggere i commenti su questa risposta - derobert .


Risposta originale

2>&1 >output.logsignifica prima iniziare a inviare tutto il file handle 2 stuff (errore standard) al file handle 1 (output standard), quindi inviarlo al file output.log. In altre parole, inviare l'errore standard e l'output standard al file di registro.

2>&1 | tee output.logè lo stesso con il 2>&1bit, combina l'output standard e l'errore standard sul flusso di output standard. Quindi lo instrada attraverso il teeprogramma che invierà il suo input standard al suo output standard (come cat) e anche al file. Quindi combina i due flussi (errore e output), quindi li invia al terminale e al file.

La linea di fondo è che il primo invia stderr/ stdoutal file, mentre il secondo lo invia sia al file che all'output standard (che è probabilmente il terminale a meno che non ci si trovi all'interno di un altro costrutto che ha reindirizzato l'output standard).

Cito quest'ultima possibilità perché puoi avere cose come:

(echo hello | tee xyzzy.txt) >plugh.txt

dove nulla finisce sul terminale.


13
-1 Hai la sintassi giusta, ma non la semantica. Esegui cat /doesnotexist 2>&1 >output.txt: vedrai cat: /doesnotexist: No such file or directoryvisualizzato sul terminale e output.txt è un file vuoto. Sono in gioco l'ordine di precedenza e la chiusura: 2>&1(duplica fd2 dall'attuale fd1), quindi >output.txt(reindirizza fd1 su output.txt, senza cambiare nient'altro). Il motivo che 2>&1 |è diverso è dovuto all'ordine di precedenza: |prima >.
Arcege,

5
Questa risposta è fondamentalmente sbagliata sotto ogni aspetto . Molte delle risposte che seguono sono migliori, ma penso che questa di Kusalananda sia la più chiara.
Michael Homer, il

2
@ user14408: se dovessi mai creare un account su Unix e Linux e richiedere questa risposta, non esitare a rimuovere la mia nota editoriale dopo aver indirizzato i commenti.
derobert

8

Il primo comando eseguirà un'altra attività:

Dopo

2>&1 > output.log 

il vecchio STDOUT verrà salvato (copiato) in STDERR e quindi STDOUT verrà reindirizzato al file.

Quindi, stdout andrà al file e stderr andrà alla console.

E dentro

 2>&1 | tee output.log

entrambi i flussi verranno reindirizzati a tee. Tee duplicherà qualsiasi input nel suo stdout (la console nel tuo caso) e in file ( output.log).

E c'è un'altra forma di prima:

    > output.log  2>&1

questo reindirizzerà STDOUT e STDERR al file.


4

Il primo restituisce solo il file. Il secondo genera sia il file che lo schermo.


4

Il motivo di ciò 2>&1 | teeè riuscire a catturare sia stdout che stderr in un file di registro e vederlo sullo schermo contemporaneamente. Anche questo potrebbe essere fatto >output.txt 2>&1 & tail -f, ma non sapresti quando il comando in background è terminato: il programma è terminato o è in esecuzione senza output. L' 2>&1 | teeera un idioma comune per i programmatori.


Intendi dire che 2> & 1> file.txt, ad esempio, non catturerebbe sia file stdout che stderr su file.txt?
Motivato il

0

Vediamo prima un po 'di codice di esempio:

#include <stdio.h>
main() 
{
// message 1, on stdout (using  printf)
printf("%s",          "message 1, on stdout (using  printf)\n");

// message 2, on stdout (using fprintf)
fprintf(stdout, "%s", "message 2, on stdout (using fprintf)\n");

// message 3, on stderr (using fprintf)
fprintf(stderr, "%s", "message 3, on stderr (using fprintf)\n");
}

Consente di confrontare i risultati:
./helloerror
+ file: nessun messaggio; console: messaggio 1,2,3;

./helloerror >error.txt
+ file: messaggio 1,2; console: messaggio 3;

./helloerror 2>&1 >error.txt
+ file: messaggio 1,2; console: messaggio 3;
+ uguale a ./helloerror> error.txt

./helloerror >error.txt 2>&1
+ file: messaggio 3,1,2; console: nessun messaggio;
+ nota che l'ordine 3 è prima, poi 1, quindi 2

./helloerror | tee error.txt 2>&1
+ file: messaggio 1,2; console: messaggio 3,1,2;
+ nota che l'ordine 3 è prima, poi 1, quindi 2

./helloerror 2>&1 | tee error.txt
+ file: messaggio 3,1,2; console: messaggio 3,1,2;

Per usare:
./helloerror >error.txt 2>&1
-> se si vogliono tutti i messaggi (stdout + stderr) nel file, ma non stampati sulla console

./helloerror 2>&1 | tee error.txt
-> se si vogliono tutti i messaggi (stdout + stderr) nel file e stampati sulla console


-1

Ecco un post che riassume i flussi di output Unix: http://www.devcodenote.com/2015/04/unix-output-streams.html

Uno snippet dal post:

Esistono 3 flussi di output standard:

STDIN - Standard Input - Writes from an input device to the program
STDOUT - Standard Output - Writes program output to screen unless specified otherwise.
STDERR - Standard Error Output - Writes error messages. Also printed to the screen unless specified otherwise.
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.