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. Je sais ce que fait 2> & 1, ma seule question est à quoi sert l'utilisation de tee où un simple opérateur de redirection ">" peut être utilisé?
En examinant les deux commandes séparément:
utility 2>&1 >output.log
Ici, puisque les redirections sont traitées de gauche à droite, le flux d'erreur standard serait d'abord redirigé vers l'endroit où le flux de sortie standard va (peut-être vers la console), puis le flux de sortie standard serait redirigé vers un fichier. Le flux d'erreur standard serait pas redirigé vers ce fichier.
L'effet visible de ceci serait que vous obtenez ce qui est produit sur l'erreur standard à l'écran et ce qui est produit sur la 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 flux both seront dirigés vers l'utilitaire tee
en tant que flux de sortie unique mélangé, et que ces données de sortie standard seront enregistrées dans le fichier donné par tee
. Les données seraient en outre reproduites par tee
dans la console (c'est ce que fait tee
, il duplique les flux de données).
Le choix de l'un d'entre eux dépend de ce que vous souhaitez réaliser.
Notez que vous ne pourrez pas reproduire l'effet du deuxième pipeline avec simplement >
(un péché utility >output.log 2>&1
, ce qui enregistrerait à la fois la sortie standard et l'erreur dans le fichier en redirigeant d'abord la sortie standard vers output.log
, puis redirige l'erreur standard vers l'endroit où la sortie standard va maintenant). Vous devrez utiliser tee
pour 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 le même 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 cependant une grande différence:
utility 2>&1 >output.log | more_stuff
utility >output.log | more_stuff
Dans le premier pipeline, more_stuff
obtiendrait ce qui était à l'origine le flux d'erreur standard de utility
en tant que ses données d'entrée standard, tandis que dans le deuxième pipeline, car ce n'est que le flux de sortie standard résultant qui est jamais envoyé via un tube, le more_stuff
une partie du pipeline n'aurait rien à lire sur son entrée standard.
Veuillez vous assurer de lire les commentaires sur cette réponse - derobert .
Réponse originale
2>&1 >output.log
signifie d'abord commencer à envoyer tous les fichiers du descripteur 2 (erreur standard) au descripteur de fichier 1 (sortie standard) puis envoyer cela au fichier output.log
. En d'autres termes, envoyez l'erreur standard et la sortie standard au fichier journal.
2>&1 | tee output.log
est le même avec le 2>&1
bit, il combine la sortie standard et l'erreur standard sur le flux de sortie standard. Il dirige ensuite cela via le programme tee
qui enverra son entrée standard vers sa sortie standard (comme cat
) et aussi dans le fichier. Il combine donc les deux flux (erreur et sortie), puis les renvoie au terminal et au fichier.
L'essentiel est que le premier envoie stderr
/stdout
au fichier, tandis que le second l'envoie à les deux le 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é parce que vous pouvez avoir des trucs comme:
(echo hello | tee xyzzy.txt) >plugh.txt
où rien ne se retrouve sur le terminal.
La première commande fera une autre tâche:
Après
2>&1 > output.log
l'ancien STDOUT sera enregistré (copié) dans STDERR puis STDOUT sera redirigé vers le 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 le tee. Tee dupliquera toute entrée dans sa sortie standard (la console dans votre cas) et dans le fichier (output.log
).
Et il y a une autre forme de première:
> output.log 2>&1
cela redirigera STDOUT et STDERR vers le fichier.
Le premier ne sort que dans le fichier. Le second renvoie à la fois au fichier et à l'écran.
La raison pour 2>&1 | tee
permet de capturer à la fois stdout et stderr dans un fichier journal et de le voir simultanément à l'écran. Cela pourrait être fait comme >output.txt 2>&1 & tail -f
également, mais vous ne sauriez pas quand la commande en arrière-plan s'est terminée - le programme est-il terminé ou s'exécute-t-il sans sortie? Le 2>&1 | tee
était un idiome courant pour les programmeurs.
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: aucun 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: aucun message;
+ notez que l'ordre 3 est d'abord, 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 d'abord, 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 l'on veut tous les messages (stdout + stderr) dans le fichier, mais pas affiché sur la console
./helloerror 2>&1 | tee error.txt
-> si l'on veut tous les messages (stdout + stderr) dans le fichier et imprimé sur la console