158 votes

Avec bash, comment puis-je faire passer l'erreur standard dans un autre processus ?

Il est bien connu que l'on peut envoyer la sortie standard d'un processus vers l'entrée standard d'un autre processus :

proc1 | proc2

Mais que faire si je veux envoyer l'erreur standard de la proc1 à la proc2 et laisser la sortie standard à son emplacement actuel ? On pourrait penser bash aurait une commande du type :

proc1 2| proc2

Mais, hélas, non. Y a-t-il un moyen de le faire ?

0 votes

Vous pouvez effectuer une redirection aussi simple dans rc qui est une autre coquille. Par exemple : proc1 |[2] proc2 . C'est beau, non ? Pas dans bash cependant.

0 votes

En rapport : Piping à la fois stdout et stderr dans bash ? . Et voici la réponse la plus simple est de canaliser à la fois stdout et stderr.

190voto

Scot Points 261

Il existe également substitution de processus . Ce qui fait qu'un processus se substitue à un fichier.
Vous pouvez envoyer stderr dans un fichier comme suit :

process1 2> file

Mais vous pouvez substituer un processus au fichier comme suit :

process1 2> >(process2)

Voici un exemple concret qui envoie stderr à la fois à l'écran et dans un fichier journal.

sh myscript 2> >(tee -a errlog)

0 votes

J'ai essayé ça. Ça n'a pas marché ( weston --help 2> >(less) ), et cela a cassé mon shell, j'ai dû quitter et me reconnecter.

2 votes

@Rolf si les deux weston --help y less s'attendent à avoir une interaction par clavier mais qu'un seul d'entre eux la reçoit, vous risquez de vous retrouver dans une situation délicate. Essayez de faire des tests avec quelque chose comme grep à la place. De plus, vous pourriez constater que les entrées de la souris et du clavier vont à la deuxième commande de toute façon plutôt qu'à Weston.

1 votes

Si vous voulez rediriger à la fois stderr et stdout utilisez |& Je l'ai appris de aquí

101voto

paxdiablo Points 341644

Vous pouvez utiliser l'astuce suivante pour swap stdout y stderr . Ensuite, il suffit d'utiliser la fonctionnalité normale des tuyaux.

( proc1 3>&1 1>&2- 2>&3- ) | proc2

Fourni stdout y stderr qui pointent tous deux au même endroit au départ, cela vous donnera ce dont vous avez besoin.

Qu'est-ce que le x>&y permet de modifier le gestionnaire du fichier x donc il envoie maintenant ses données à n'importe quel handle de fichier y actuellement des points. Pour notre cas spécifique :

  • 3>&1 crée un nouveau poignée 3 qui donnera lieu à une sortie vers le actuel poignée 1 (stdout original), juste pour le sauvegarder quelque part pour le dernier point ci-dessous.
  • 1>&2 modifie la poignée 1 (stdout) pour sortir sur le actuel poignée 2 (stderr original).
  • 2>&3- modifie la poignée 2 (stderr) pour la sortie vers le actuel poignée 3 (stdout original) puis ferme le handle 3 (via le - à la fin).

C'est effectivement la commande de permutation que l'on voit dans les algorithmes de tri :

temp   = value1;
value1 = value2;
value2 = temp;

4 votes

Quel est l'intérêt d'utiliser 1>&2- ici plutôt que de simplement 1>&2 ? Je ne comprends pas pourquoi on voudrait fermer FD. 2 si nous devons le rouvrir ou le réassigner immédiatement.

2 votes

@dubiousjim, aucun avantage dans ce cas particulier, je pense que je l'ai fait juste pour être cohérent - fermer la poignée de fichier 3 est une bonne idée pour la libérer.

0 votes

Bon point, @ovgolovin, je ne peux pas croire que personne ne l'ait remarqué en sept mois depuis que j'ai fait cette modification. Corrigé selon votre suggestion.

79voto

Dennis Williamson Points 105818

Bash 4 possède cette fonctionnalité :

Si `|&' est utilisé, l'erreur standard de la commande1 est connectée à l'entrée standard de la commande2 à travers le pipe ; c'est un raccourci pour 2>&1 |. Cette redirection implicite de l'erreur standard est effectuée après toute redirection spécifiée par la commande.

zsh possède également cette fonctionnalité.

--

Avec les autres shells/anciens shells, il suffit de l'entrer explicitement en tant que

PremièreCommande 2>&1 | AutreCommande

16 votes

D'après la lecture de la documentation, cela fait à la fois l'erreur standard y par opposition à stderr, mais c'est bon à savoir. Il est temps de commencer à regarder bash 4, je pense.

0 votes

Le manuel actuel de bash indique "Si |& est utilisé, l'erreur standard de la commande, en plus de sa sortie standard, est connecté à l'entrée standard de command2". Ce n'est explicitement pas ce que le PO veut.

0 votes

@PeterA.Schneider : L'OP dit "laisser la sortie standard aller à son emplacement actuel", ce qui peut être ambigu.

32voto

kccqzy Points 541

L'échange est une bonne chose car il résout le problème. Au cas où vous n'auriez même pas besoin du stdout original, vous pouvez le faire de cette façon :

proc1 2>&1 1>/dev/null | proc2

L'ordre est vital ; vous ne voudriez pas :

proc1 >/dev/null 2>&1 | proc1

Comme cela va tout rediriger vers /dev/null !

3voto

sbingner Points 66

Aucune d'entre elles n'a vraiment bien fonctionné. La meilleure façon que j'ai trouvée pour faire ce que vous voulez est :

(command < input > output) 2>&1 | less

Cela ne fonctionne que dans les cas où command ne nécessite pas de saisie au clavier, par exemple

(gzip -d < file.gz > file) 2>&1 | less

mettrait les erreurs gzip dans less

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X