2009-10-02 14 views
93

Il est bien connu comment redirigez la ouput standard d'un processus dans un autre processus d'entrée standard:Avec bash, comment puis-je rediriger l'erreur standard dans un autre processus?

proc1 | proc2 

Mais si je veux envoyer l'erreur type de PROC1 à proc2 et laisser la sortie standard va à son courant emplacement? Vous penseriez bash aurait une commande le long des lignes de:

proc1 2| proc2 

Mais, hélas, pas. Est-ce qu'il y a un moyen de faire ça?

+0

Vous pouvez effectuer une redirection simple dans 'rc', qui est un autre shell. Par exemple: 'proc1 | [2] proc2'. N'est-ce pas gentil? Pas dans 'bash' cependant. – Rolf

Répondre

75

Vous pouvez utiliser l'astuce suivante pour échangerstdout et stderr. Ensuite, vous utilisez simplement la fonctionnalité de tuyau régulière.

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

fourni stdout et stderr souligné à la fois au même endroit au début, cela vous donnera ce dont vous avez besoin.

Ce qu'il fait:

  • 3>&1 crée un nouveau fichier poignée 3 qui est réglé sur la 1 actuelle (stdout d'origine) juste pour enregistrer quelque part.
  • 1>&2- définit stdout pour obtenir le fichier en cours gérer 2 (original stderr) puis ferme 2.
  • 2>&3- définit stderr pour obtenir le fichier en cours gérer 3 (stdout d'origine) puis ferme 3.

Il est effectivement la commande d'échange que vous voyez dans le tri:

temp = value1; 
value1 = value2; 
value2 = temp; 
+3

Quelle est la valeur d'utiliser '1> & 2-' ici plutôt que simplement '1> & 2'? Je ne comprends pas pourquoi nous voudrions fermer fd '2', si nous allons simplement le rouvrir/le réaffecter immédiatement. – dubiousjim

+1

@dubiousjim, aucun avantage dans ce cas particulier, je suppose que je l'ai fait juste pour être cohérent - fermeture du fichier handle 3 est une bonne idée pour le libérer. – paxdiablo

+0

Vous avez probablement oublié '&' dans les explications de bullet-point. – ovgolovin

56

Bash 4 a cette fonction:

Si `| & 'est utilisé, l'erreur standard de la commande 1 est connectée à l'entrée standard de command2 à travers le tuyau; 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 d'autres/coquilles plus anciennes, il suffit d'entrer explicitement comme

FirstCommand 2> & 1 | OtherCommand

+11

A la lecture des docs, cela fait à la fois l'erreur standard * et * la sortie par opposition à juste stderr, mais c'est bon à savoir. Il est temps de commencer à regarder bash 4, je pense. – paxdiablo

+0

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

+0

@ PeterA.Schneider: L'OP dit "laisser la sortie standard aller à sa position actuelle" ce qui peut être ambigu. –

18

La permutation est excellente car elle résout le problème.Juste au cas où vous n'avez même pas besoin de la sortie d'origine, vous pouvez le faire de cette façon:

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

La commande est vitale; vous ne voudriez pas:

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

Comme il redirigera tout à /dev/null!

108

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

process1 2> file 

Mais vous pouvez remplacer un processus pour le fichier comme suit:

process1 2> >(process2) 

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

sh myscript 2> >(tee -a errlog) 
+14

Ceci répond correctement à la question posée et devrait être la réponse acceptée par @paxdiablo – mmlb

+0

J'ai essayé ceci. Cela n'a pas fonctionné ('weston --help 2>> (less)'), et cela a cassé mon shell, j'ai dû quitter et me reconnecter. – Rolf