Que fera cette commande?
exec 2>&1
Techniquement parlant, il duplique ou copie stderr sur stdout.
Habituellement, vous n'avez pas besoin de l'exécutif pour le faire. Une utilisation plus typique de exec avec des descripteurs de fichier consiste à indiquer que vous souhaitez affecter un fichier à un descripteur de fichier inutilisé, par exemple.
ls > mydirlist 2>&1
fonctionnera, car il dirige à la fois stdout et stderr vers le fichier mydirlist, alors que la commande
ls 2>&1 > mydirlist
demande uniquement à stdout, et non à stderr, de classer mydirlist, car stderr a été créé comme une copie de stdout avant que stdout ne soit redirigé vers mydirlist.
Edit: C’est la façon dont le shell balaye de gauche à droite. Lisez donc le second en disant "Copiez stderr sur stdout" avant "envoyer stdout à mydirlist". Lisez ensuite le premier en disant "envoyez stdout au fichier mydirlist" avant "duplicate stderr sur le stdout que j'ai configuré". Je connais. C'est totalement pas intuitif!
Un des meilleurs articles que j'ai vu sur ce que "2> & 1" fait est Bash One-Liners Explained, Partie III: Tout sur les redirections .
Mais ce que les réponses actuelles à cette question ne fournissent pas, c'est pourquoi vous voudriez le faire après un simple "exec". Comme l'explique la page de manuel bash de la commande exec: "Si aucune commande n'est spécifiée, les redirections prennent effet dans le shell en cours".
J'ai écrit un script simple appelé out-and-err.py
qui écrit une ligne de sortie sur stdout et une autre ligne sur stderr:
#!/usr/bin/python
import sys
sys.stdout.write('this is stdout.\n')
sys.stderr.write('this is stderr.\n')
Et puis j'ai enveloppé cela dans un script Shell appelé out-and-err.sh avec un "exec 2> & 1":
#!/bin/bash
exec 2>&1
./out-and-err.py
Si je lance uniquement le script python, stdout et stderr sont séparés:
$ ./out-and-err.py 1> out 2> err
$ cat out
this is stdout.
$ cat err
the is stderr.
Mais si j'exécute le script Shell, vous pouvez voir que l'exécutif s'occupe de stderr pour tout ce qui suit:
$ ./out-and-err.sh 1> out 2> err
$ cat out
this is stdout.
this is stderr.
$ cat err
$
Si votre script de shell enveloppe fait beaucoup plus que la seule commande python et que vous avez besoin de toutes les sorties combinées dans stdout, exécuter "exec 2> & 1" vous facilitera la tâche.
Il lie l'erreur standard à la sortie standard
le 2
est stderr et 1
est stdout. Lorsque vous exécutez un programme, vous obtenez la sortie normale dans stdout, mais toutes les erreurs ou tous les avertissements sont généralement envoyés à stderr. Si vous souhaitez par exemple diriger toute la sortie vers un fichier, il est utile de commencer par combiner stderr avec stdout avec 2>&1
.
Comme @cma a dit, il place stderr sur stdout. La raison pour laquelle vous pourriez souhaiter ce comportement est d'utiliser grep ou tout autre utilitaire pour capturer une sortie qui apparaît uniquement sur stderr. Ou vous voudrez peut-être simplement sauvegarder toute la sortie, y compris stderr, dans un fichier pour un traitement ultérieur.
Ce jour-là, je suis aussi insensible à ce problème, mais maintenant je m'en échappe . Permettez-moi donc de vous expliquer ce qui se passe après la saisie de exec 1>&2
dans la CLI.
Je veux détruire le problème pièce par pièce, donc si vous connaissez déjà vos connaissances, effacez-les pour économiser votre temps.
exec
signifie:exec
est une commande intégrée à Linux. exec
peut changer le processus Shell actuel, à la différence de la commande tradition qui consiste simplement à créer un sous-processus Shell.
Qu'est-ce que la redirection d'E/S: La redirection est une fonctionnalité de Linux. Avec cela, vous pouvez changer les périphériques d'entrée/sortie standard. Sous Linux, il existe trois descripteurs de fichier par défaut .
Handle Name Description
0 stdin Standard input
1 stdout Standard output
2 stderr Standard error
Laissez-moi voir un exemple:
$ pstree -p | grep 'term' | tr -d ' '
$ Sudo ls -l /proc/{pid}/fd
bash
$ pstree -p | grep -i 'terminal' | tr -d ' '
||||-gnome-terminal-(6008)-+-bash(7641)-+-grep(8355)
$ Sudo ls -l /proc/7641/fd
total 0
lrwx------ 1 alopex alopex 64 Oct 27 19:39 0 -> /dev/pts/3
lrwx------ 1 alopex alopex 64 Oct 27 19:39 1 -> /dev/pts/3
lrwx------ 1 alopex alopex 64 Oct 27 19:39 2 -> /dev/pts/3
lrwx------ 1 alopex alopex 64 Oct 27 19:39 255 -> /dev/pts/3
Comme vous pouvez le voir, la liste ls
répertorie le fichier de processus PID (6860). D'abord, ils s'appellent tous par leur numéro (0, 1, 2), ensuite, ils lient tous un lien de fichier à/dev/pts/3, cela signifie que toutes les entrées/sorties/erreurs standard apparaîtront dans pts3.bash
$ ls /tmp/stdout
ls: cannot access '/tmp/stdout': No such file or directory
$ exec 1>/tmp/stdout
$ ls
$ pwd
$ echo "Are you ok"
$
La sortie de la commande a disparu à ce moment-là.bash
$ Sudo ls -l /proc/7641/fd
total 0
lrwx------ 1 alopex alopex 64 Oct 27 19:39 0 -> /dev/pts/3
lrwx------ 1 alopex alopex 64 Oct 27 19:39 1 -> /tmp/stdout
lrwx------ 1 alopex alopex 64 Oct 27 19:39 2 -> /dev/pts/3
lrwx------ 1 alopex alopex 64 Oct 27 19:39 255 -> /dev/pts/3
De toute évidence, nous pouvons remarquer que le 1 (descripteur de fichier) change déjà de lien avec/tmp/stdout. Comme nous sauf, le transfert de sortie standard vers/tmp/stdoutbash
$ exec 1>&2
$ cat /tmp/stdout
a.sh
/home/alopex
Are you ok
$ Sudo ls -l /proc/7641/fd
total 0
lrwx------ 1 alopex alopex 64 Oct 27 19:39 0 -> /dev/pts/3
lrwx------ 1 alopex alopex 64 Oct 27 19:39 1 -> /dev/pts/3
lrwx------ 1 alopex alopex 64 Oct 27 19:39 2 -> /dev/pts/3
lrwx------ 1 alopex alopex 64 Oct 27 19:39 255 -> /dev/pts/3
Là encore, le lien 1 (descripteur de fichier) vers/dev/pts/3 permet de voir à nouveau la sortie.Résumé:
exec 1>&2
faire la sortie standard ---> erreur standardUne application très utile de exec 2>&1
que j'ai rencontrée est la fusion de stderr
et stdout
pour plusieurs commandes séparées par des points-virgules. Mon exemple particulier s’est produit lorsque j’envoyais plus d’une commande à popen
dans PHP et que je souhaitais voir les erreurs entrelacées comme si vous verriez si vous tapez les commandes à une invite du shell:
$ echo hi ; yikes ; echo there
hi
-bash: yikes: command not found
there
$
Ce qui suit ne fusionne pas stderr
et stdout
à l'exception de la dernière echo
(inutile) car yikes
provoque l'erreur:
echo hi ; yikes ; echo there 2>&1
Je peux obtenir la sortie fusionnée à la "dure" comme suit:
echo hi 2>&1; yikes 2>&1; echo there 2>&1
Cela semble beaucoup plus propre et moins sujet aux erreurs si vous utilisez exec
:
exec 2>&1 ; echo hi; echo yikes; echo there
Vous obtenez les sorties stdout
et stderr
bien entrelacées exactement comme vous le verrez sur le terminal si vous exécutiez les trois commandes séparées par un point-virgule.