60 votes

Comment puis-je rediriger STDERR vers STDOUT, mais ignorer le STDOUT original ?

J'ai un programme dont STDERR sortie que je veux inspecter et exécuter grep etc.

Je pourrais donc le rediriger vers STDOUT et utiliser grep, mais le problème est que je fais pas veulent l'original STDOUT contenu.

Donc, celui-là ne fera pas l'affaire.

cmd 2>&1 | grep pattern

car il mélangera les STDOUT et STDERR originaux.

Et celle-ci ne fonctionne pas puisque grep ne lit pas la sortie STDERR :

cmd 1>/dev/null | grep pattern

Mais aussi, celui-là ne marchera pas :

cmd 1>/dev/null 2>&1 | grep pattern

car la sortie sera complètement vide, puisque tout est écrit dans le fichier /dev/null .

Mais il doit y avoir un moyen simple de le faire ?

104voto

Tom Alsberg Points 3253

Ce qui ne fonctionne pas :

La raison de la dernière commande que vous avez citée :

cmd 1>/dev/null 2>&1 | grep pattern

ne fonctionne pas, provient d'une confusion sur l'ordre dans lequel la redirection fonctionne. Vous vous attendiez à ce que la dernière redirection citée soit appliquée à celles qui la précèdent sur chaque sortie, de sorte que la sortie du descripteur de fichier de sortie standard original (1) aille vers /dev/null, et que la sortie vers le descripteur de fichier d'erreur standard (2) aille vers la sortie standard originale.

Toutefois, ce n'est pas ainsi que fonctionne la redirection de l'interpréteur de commandes. Chaque redirection entraîne le "remappage" des descripteurs de fichiers en fermant la "source" et en dupliquant la "destination" dans celle-ci (voir l'instruction man pages de dup(2) et close(2) ), dans l'ordre. Cela signifie que dans votre commande la sortie standard est d'abord remplacée par /dev/null et l'erreur standard est remplacée par la sortie standard, soit /dev/null déjà.

Ce qui marche :

Par conséquent, pour obtenir l'effet désiré, il suffit d'inverser les redirections. Ainsi, l'erreur standard sera redirigée vers la sortie standard, et la sortie standard originale sera redirigée vers /dev/null :

cmd 2>&1 >/dev/null | grep pattern

(notez que le 1 avant > n'est pas nécessaire - pour la redirection de la sortie, la sortie standard est la valeur par défaut)


Addendum : Charlie a mentionné la redirection vers &- pour fermer un descripteur de fichier. Si vous utilisez un shell interactif qui supporte cette extension ( bash et certaines autres implémentations le font mais pas toutes et c'est non standard ), vous pouvez également procéder de la manière suivante :

cmd 2>&1 >&- | grep pattern

C'est peut-être mieux - cela peut faire gagner du temps, car lorsque la commande essaie d'écrire sur la sortie standard, l'appel à write peut échouer immédiatement sans attendre un changement de contexte dans le noyau et la gestion du pilote. /dev/null (en fonction de l'implémentation de l'appel système - certains peuvent l'attraper dans l'appel système de l'utilisateur). libc et certains peuvent également avoir un traitement spécial pour les fonctions /dev/null ). S'il y a beaucoup de sorties, cela peut être intéressant, et c'est plus rapide à taper.

Cela fonctionnera surtout parce que la plupart des programmes ne se soucient pas de ne pas écrire sur la sortie standard (qui vérifie vraiment la valeur de retour de la commande printf ?) et ne se souciera pas que la sortie standard soit fermée. Mais certains programmes peuvent se sauver avec un code d'échec si write échoue - généralement les processeurs de blocs, les programmes utilisant une bibliothèque prudente pour les E/S ou la journalisation vers la sortie standard. Donc si cela ne fonctionne pas, rappelez-vous que c'est une cause probable et essayez de /dev/null .

4voto

Charlie Martin Points 62306

Fermez d'abord STDOUT :

1>&-, >&-

Voir ici .

-4voto

Martin Cote Points 12762

J'essaierais quelque chose de simple comme :

cmd 2> tmp_file && cat tmp_file | grep pattern && rm -f tmp_file

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