Différence entre 2> & 1> output.log et 2> & 1 | tee output.log

35

Je voulais connaître la différence entre les deux commandes suivantes

2>&1 > output.log 

et

2>&1 | tee output.log

J'ai vu un de mes collègues utiliser la deuxième option pour rediriger les messages. Je sais ce que 2> & 1 fait, ma seule question est quel est le but de l’utilisation de tee où un simple opérateur de redirection ">" peut être utilisé?

Chander Shivdasani
la source

Réponses:

11

En regardant les deux commandes séparément:

utility 2>&1 >output.log 

Ici, les redirections étant traitées de gauche à droite, le flux d'erreur standard serait d'abord redirigé vers l'endroit où le flux de sortie standard se rend (éventuellement vers la console), puis le flux de sortie standard était redirigé vers un fichier. Le flux d'erreur standard ne serait pas redirigé vers ce fichier.

L'effet visible de ceci serait que vous obtenez ce qui est produit avec une erreur standard à l'écran et ce qui est produit avec une sortie standard dans le fichier.

utility 2>&1 | tee output.log

Ici, vous redirigez l'erreur standard au même endroit que le flux de sortie standard. Cela signifie que les deux flux seront acheminés vers l' teeutilitaire en tant que flux de sortie entremêlé et que les données de sortie standard seront enregistrées dans le fichier donné tee. Les données seraient en outre reproduites par teedans la console (c'est ce qui teefait, cela duplique les flux de données).

Quel que soit le type utilisé, cela dépend de ce que vous souhaitez réaliser.

Notez que vous ne pourrez pas reproduire l’effet du deuxième pipeline avec juste >(comme dans utility >output.log 2>&1, ce qui sauverait la sortie standard et les erreurs dans le fichier). Vous devrez utiliser teepour obtenir les données dans la console ainsi que dans le fichier de sortie.


Notes complémentaires:

L' effet visible de la première commande,

utility 2>&1 >output.log 

serait la même chose que

utility >output.log

C'est-à-dire que la sortie standard va au fichier et l'erreur standard va à la console.

Si une étape de traitement supplémentaire était ajoutée à la fin de chacune des commandes ci-dessus, il y aurait une grande différence cependant:

utility 2>&1 >output.log | more_stuff

utility >output.log      | more_stuff

Dans le premier pipeline, les données d'entrée standard contiennent more_stuffce qui était à l'origine le flux d'erreur utilitystandard, tandis que dans le second pipeline, étant donné que seul le flux de sortie standard résultant est envoyé dans un canal, la more_stuffpartie du pipeline n'obtient rien à lire sur son entrée standard.

Kusalananda
la source
Par la commande " utility 2>&1 | tee output.log, voulez-vous dire que, puisque 1 est dirigé vers tee, le reste est aussi 2. Puisque tee duplique le flux, le résultat est affiché à la fois sur la console et écrit dans un fichier. D'où la différence entre utility 2>&1 > output.loget utility 2>&1 | tee output.logest teeen ce sens qu'il fait double emploi avec le flux serait - ce correct.?
Motivé
Avec les exemples de utility 2>&1 > output.log | more_stuffet utility >ouput.log| more_stuff , is the difference that more_stuff` a la sortie d'erreur standard sur la console en tant qu'entrée more_stuff? Comme dans le deuxième exemple, il n'y a pas de sortie sur la console, il n'y a pratiquement pas d'entrée à more_stuff? Si oui, ce n'est pas clair puisque le paragraphe précédent indique que la sortie standard va au fichier et l'erreur standard va à la console.
Motivé le
@ Motivé Votre premier commentaire me semble correct, oui. En ce qui concerne le deuxième commentaire: Dans la première commande, more_stuffrecevrait ce qui avait utilityété envoyé à l'origine à son flux d'erreur (mais qui était redirigé vers la sortie standard). Pas parce que cela se retrouverait sur la console s'il more_stuffn'y en avait pas, mais parce que cela irait au flux de sortie standard . Dans la deuxième commande, rien n'estmore_stuff reçu car il n'y a pas de sortie standard du côté gauche du pipeline. Le flux d'erreur de finira toujours sur la console dans la 2ème commande. utility
Kusalananda
Merci. Voulez-vous dire que parce que la commande utility > output.log | more_stuffn'entraîne pas une sortie dans le flux de sortie standard d'un point de vue d'erreur standard?
Motivé le
@Motivated Puisque le côté gauche ne produit rien sur la sortie standard (il est redirigé), aucune donnée ne sera envoyée sur le canal.
Kusalananda
24

Note éditoriale

Assurez-vous de lire les commentaires sur cette réponse - derobert .


Réponse originale

2>&1 >output.logsignifie commencer par envoyer tous les fichiers 2 (erreur standard) au fichier 1 (sortie standard), puis les envoyer au fichier output.log. En d'autres termes, envoyez l'erreur standard et la sortie standard au fichier journal.

2>&1 | tee output.logest identique au 2>&1bit, il associe une sortie standard et une erreur standard au flux de sortie standard. Il passe ensuite cela dans le teeprogramme qui enverra son entrée standard à sa sortie standard (comme cat) et également au fichier. Donc, il combine les deux flux (erreur et sortie), puis les envoie au terminal et au fichier.

L'essentiel est que le premier envoie stderr/ stdoutau fichier, tandis que le second l'envoie à la fois au fichier et à la sortie standard (qui est probablement le terminal sauf si vous êtes dans une autre construction qui a redirigé la sortie standard).

Je mentionne cette dernière possibilité car vous pouvez avoir des choses comme:

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

où rien ne se termine sur le terminal.

derobert
la source
13
-1 Vous avez la syntaxe correcte, mais pas la sémantique. Run cat /doesnotexist 2>&1 >output.txt- vous verrez voir cat: /doesnotexist: No such file or directoryaffiché au terminal et output.txt est un fichier vide. L'ordre de priorité et de fermeture sont en jeu: 2>&1(dup fd2 à partir du fd1 actuel ), puis >output.txt(redirigez fd1 vers output.txt, sans rien changer d'autre). La raison en 2>&1 |est différente à cause de l'ordre de priorité: |avant >.
Arcege
5
Cette réponse est fondamentalement fausse à presque tous les égards . Beaucoup des réponses ci-dessous sont meilleures, mais je pense que celle de Kusalananda est la plus claire.
Michael Homer
2
@ user14408: Si jamais vous créez un compte sous Unix & Linux et revendiquez cette réponse, n'hésitez pas à supprimer ma note éditoriale une fois que vous avez répondu aux commentaires.
derobert
8

La première commande fera l’autre tâche:

Après

2>&1 > output.log 

l'ancien STDOUT sera sauvegardé (copié) dans STDERR, puis STDOUT sera redirigé vers un fichier.

Donc, stdout ira dans le fichier et stderr ira dans la console.

Et en

 2>&1 | tee output.log

les deux flux seront redirigés vers tee. Tee dupliquera toutes les entrées sur sa sortie standard (la console dans votre cas) et dans le fichier ( output.log).

Et il y a une autre forme de premier:

    > output.log  2>&1

cela redirigera les fichiers STDOUT et STDERR vers le fichier.

osgx
la source
4

Le premier ne sort que dans le fichier. La deuxième sortie à la fois dans le fichier et à l'écran.


la source
4

La raison en 2>&1 | teeest de pouvoir capturer stdout et stderr dans un fichier journal et de le voir à l'écran en même temps. Cela pourrait également être fait >output.txt 2>&1 & tail -f, mais vous ne sauriez pas quand la commande en arrière-plan sera terminée - le programme est-il terminé ou est-il en cours d'exécution sans sortie? Le 2>&1 | teeétait un idiome commun pour les programmeurs.

Arcege
la source
Voulez-vous dire que 2> & 1> fichier.txt, par exemple, ne capturerait ni stdout ni stderr en fichier.txt?
Motivé le
0

Voyons d'abord un exemple de code:

#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");
}

Permet de comparer les résultats:
./helloerror
+ fichier: pas de message; console: message 1,2,3;

./helloerror >error.txt
+ fichier: message 1,2; console: message 3;

./helloerror 2>&1 >error.txt
+ fichier: message 1,2; console: message 3;
+ identique à ./helloerror> error.txt

./helloerror >error.txt 2>&1
+ fichier: message 3,1,2; console: pas de message;
+ notez que l'ordre 3 est le premier, puis 1, puis 2

./helloerror | tee error.txt 2>&1
+ fichier: message 1,2; console: message 3,1,2;
+ notez que l'ordre 3 est le premier, puis 1, puis 2

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

Pour utiliser:
./helloerror >error.txt 2>&1
-> si on veut tous les messages (stdout + stderr) dans un fichier, mais pas sur la console

./helloerror 2>&1 | tee error.txt
-> si on veut tous les messages (stdout + stderr) dans un fichier et imprimés sur la console

Hari Perev
la source
-1

Voici un article résumant les flux de sortie Unix: http://www.devcodenote.com/2015/04/unix-output-streams.html

Un extrait du message:

Il existe 3 flux de sortie 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.
Abhishek Jain
la source