commande sh: exec 2 > & 1

Que fera cette commande?

exec 2>&1 
35
demandé sur R. Martinho Fernandes 2009-08-01 20:17:31

5 réponses

Techniquement parlant, il duplique, ou copie, stderr sur stdout.

Généralement, vous n'avez pas besoin de l'exec pour effectuer cela. Une utilisation plus typique d'exec avec des descripteurs de fichier est d'indiquer que vous souhaitez attribuer un fichier à un descripteur de fichier inutilisé, par exemple

exec 35< my_input

BTW N'oubliez pas que la séquence de déclaration lors de la redirection vers un fichier est importante, donc

ls > mydirlist 2>&1

Fonctionnera car il dirige à la fois stdout et stderr vers le fichier mydirlist, alors que le commande

ls 2>&1 > mydirlist

Dirige uniquement stdout, et non stderr, vers le fichier mydirlist, car stderr a fait une copie de stdout avant que stdout ne soit redirigé vers mydirlist.

Edit: c'est la façon dont le shell fonctionne en scannant de gauche à droite. Alors lisez le second comme disant "copier stderr sur stdout" avant de dire "envoyer stdout à mydirlist". Ensuite, lisez le premier comme disant "envoyer stdout au fichier mydirlist" avant de dire "dupliquer stderr sur ce stdout que j'ai mis en place". Je savoir. C'est absolument pas intuitif!

32
répondu Rob Wells 2009-08-01 17:50:58

L'un des meilleurs articles que j'ai vu sur ce que" 2>&1 " fait est Bash One-Liners Explained, Part III: All about redirections .

Mais ce que les réponses actuelles sur cette question ne parviennent pas à fournir, c'est pourquoi vous voudriez le faire après un simple "exec". Comme l'explique la page de manuel bash pour la commande exec: "si la commande n'est pas spécifiée, toutes les redirections prennent effet dans le shell actuel".

J'ai écrit un script simple appelé {[4] } qui écrit une ligne de sortie vers stdout, et une autre ligne vers 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 juste 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'exec s'occupe de stderr pour tout après:

$ ./out-and-err.sh 1> out 2> err
$ cat out
this is stdout.
this is stderr.
$ cat err
$

Si votre script shell d'emballage fait beaucoup plus que la seule commande python, et que vous avez besoin de toutes les sorties combinées dans stdout, faire le "exec 2> & 1" fera que facile pour vous.

25
répondu Brian Taylor 2018-05-14 10:15:25

Il lie l'erreur standard à la sortie standard

Le 2 est stderr et 1 est la sortie standard stdout. Lorsque vous exécutez un programme, vous obtiendrez la sortie normale dans stdout, mais les erreurs ou les Avertissements vont généralement à stderr. Si vous voulez acheminer toutes les sorties vers un fichier par exemple, il est utile de combiner d'abord stderr avec stdout avec 2>&1.

11
répondu Charles Ma 2009-08-02 00:40:30

Comme l'a dit @cma, il met stderr sur stdout. La raison pour laquelle vous pouvez vouloir ce comportement est d'utiliser grep ou tout autre utilitaire pour capturer la sortie qui apparaît uniquement sur stderr. Ou vous pouvez simplement enregistrer toute la sortie, y compris stderr, dans un fichier pour un traitement ultérieur.

2
répondu Mark Rushakoff 2009-08-01 16:21:03

Une application très utile de exec 2>&1 que j'ai rencontrée est quand vous voulez fusionner stderr et stdout pour plusieurs commandes séparées par des points-virgules. Mon exemple particulier est arrivé quand j'envoyais plus d'une commande à popen en PHP et je voulais voir les erreurs entrelacées comme vous le verriez si vous tapiez les commandes à une invite shell:

$ echo hi ; yikes ; echo there
hi
-bash: yikes: command not found
there
$ 

Ce qui suit ne fusionne pas stderr et stdout sauf pour le dernier echo (ce qui est inutile car le yikes provoque le 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

Il semble beaucoup plus propre et moins sujet aux erreurs si vous utilisez exec:

exec 2>&1 ; echo hi; echo yikes; echo there

Vous obtenez la sortie stdout et stderr bien entrelacée exactement comme vous le verriez sur le terminal si vous exécutiez les trois commandes séparées par un point-virgule.

0
répondu drchuck 2016-12-27 05:17:36