web-dev-qa-db-fra.com

commande sh: exec 2> & 1

Que fera cette commande? 

exec 2>&1 
40
valodzka

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!

33
Rob Wells

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.

29
Brian Taylor

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.

12
Charles Ma

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.

2
Mark Rushakoff

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.

  • Qu'est-ce que 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:

    1. ouvrir un nouveau terminal
    2. Obtenir l'identifiant du processus termianl $ pstree -p | grep 'term' | tr -d ' '
    3. Vérifiez le descripteur de fichier de processus .$ Sudo ls -l /proc/{pid}/fdbash $ 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.
    4. Modifiez la sortie standard en /tmp/stdoutbash $ 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à.
    5. Ouvrez un nouveau terminal, pour vérifier le fichier proc 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/stdout
    6. Restaurez la redirection .bash $ 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 standard
0
Alopex

Une 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.

0
drchuck