Je suis tombé sur plusieurs commandes qui utilisent 2>&1
et 1>&2
, mais je ne peux vraiment pas comprendre le but de l’utiliser ni le moment où je devrais l’utiliser.
Ce que je comprends
Je sais que 1
représente la sortie standard et 2
représente l'erreur standard. Je comprends que 2>&1
combine le résultat de 2
à 1
et vice versa.
Ce que je ne comprends pas
Parfois, vous souhaitez rediriger stdout et stderr vers le même emplacement. C’est lorsque >&
est utilisé - il pointe un descripteur de fichier vers un autre.
Par exemple, si vous voulez écrire stdout et stderr dans le même fichier (que ce soit /dev/null
ou output.txt
), vous pouvez les rediriger séparément, avec
app 1>/dev/null 2>/dev/null
ou vous pouvez rediriger un descripteur de fichier vers le fichier et l’autre descripteur de fichier dans le premier:
app 1>/dev/null 2>&1
app 2>/dev/null 1>&2
Dans le premier exemple, 2>&1
pointe le descripteur de fichier n ° 2 sur le pointeur n ° 1. Le deuxième exemple obtient le même résultat, en commençant par stderr.
Autre exemple, il existe des cas où stdout (descripteur de fichier n ° 1) pointe déjà vers l'emplacement souhaité, mais vous ne pouvez pas y faire référence par son nom (il peut être associé à un tuyau, à un socket, etc.). Cela se produit souvent lorsqu’on utilise l’extension de processus (les opérateurs ` `
ou $( )
), qui ne capture normalement que stdout, mais vous voudrez peut-être y inclure stderr. Dans ce cas, vous utiliseriez également >&
pour pointer stderr sur stdout:
out=$(app 2>&1)
Un autre exemple courant est un pager, ou grep
, ou un utilitaire similaire, puisque le tube |
ne fonctionne normalement que sur stdout; vous redirigeriez stderr vers stdout avant d'utiliser le canal:
app 2>&1 | grep hello
Comment savoir lequel de 2>&1
ou 1>&2
est correct? Le descripteur de fichier déjà configuré se place à droite de >&
et le descripteur de fichier que vous souhaitez rediriger se place à gauche. (2>&1
signifie "descripteur de fichier de point n ° 2 au descripteur de fichier n ° 1".)
Certains shells ont des raccourcis pour les redirections courantes; voici des exemples de Bash:
1>
peut être réduit à seulement >
1>foo 2>&1
à >&foo
ou &>foo
2>&1 | program
à |& program
Parfois, vous souhaitez rediriger stdout
(1
) et stderr
(2
) vers le même emplacement (/dev/null
, par exemple). Un moyen d'y parvenir serait:
$ program 1>/dev/null 2>/dev/null
Mais la plupart des gens raccourcissent cela en redirigeant stderr
vers stdout
avec 2>&1
:
$ program 1>/dev/null 2>&1
Une version encore plus courte est:
$ program >&- 2>&-
Lorsque vous en avez besoin, vous pouvez par exemple afficher la sortie strace
dans un pager. strace
affiche sa sortie en erreur standard et les tuyaux connectent généralement la sortie standard à entrée standard, vous devez donc utiliser la redirection:
strace -p $pid 2>&1 | less
2: C'est pour quand vous aurez une sortie venant à la fois d'erreur standard et standard, et que vous voulez les composer en une seule chaîne.
1: Lorsque vous voulez manipuler la sortie d'erreur standard et sortie standard.
Le cas de la redirection de stderr sur stdout a déjà été traité ici (par exemple, utilisez-le pour filtrer les messages d'erreur (grep)).
L'autre cas est la redirection de stdout vers stderr. Un cas d'utilisation courant (du moins pour moi) consiste à envoyer des avertissements/messages d'erreur avec "echo" (dans mes scripts de shell) au stderr (afin qu'ils puissent attirer plus facilement l'attention de l'utilisateur).
Par exemple,
echo "file \"${file\" does not exist..." 1>&2
Scénario alternatif: les commandes du terminal affichent la sortie dans un autre terminal
Utilisez la commande tty
dans chaque terminal pour les identifier:
$ tty
/dev/pts/0
$ tty
/dev/pts/1
En supposant que ces TTY, pour rediriger la sortie standard du premier à la seconde, exécutez ceci dans le premier terminal:
exec 1>/dev/pts/1
Remarque: Maintenant chaque sortie de commande s'affichera sur pts/1
Pour restaurer le comportement par défaut de la sortie standard de pts/0:
exec 1>/dev/pts/0
Voir cette vidéo pour une démonstration.
Je l'utilise pour commencer un travail détaché:
someProgram 2>&1 >& my.log &
alors je peux me déconnecter, et someProgram sera toujours en cours d'exécution. La fonctionnalité est fournie par GNU Screen, tmux et quelques autres programmes - mais ici, elle est réalisée sans aucune dépendance externe.
Imaginez qu’il existe un répertoire nommé try
qui contient ces trois fichiers: file file1 and file2.
Maintenant, lancez cette commande:
cat file file1 file2 file3
Les trois premiers fichiers sont ouverts mais cat
génère une erreur lors de l’ouverture du quatrième, car il n’existe pas.
Maintenant, lancez:
cat file file1 file2 file3 1>outfile 2>&1
Vous ne verrez aucune sortie à l'écran. Tout d'abord, 1>outfile
redirige la sortie de la commande vers outfile
, puis redirigera (2>&1
) l'erreur renvoyée lors de la tentative d'ouverture de file3
à outfile
.
1>&2
fonctionne de manière similaire et redirige le flux d’erreurs vers la sortie standard.
J'espère que cela t'aides!