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

cette question a déjà une réponse ici:

j'ai un programme dont STDERR Sortie je veux inspecter et exécuter grep sur etc.

pour que je puisse le rediriger vers STDOUT et utiliser grep, mais le problème est, je ne pas veulent l'original STDOUT du contenu.

Donc, ce ne sera pas le faire

cmd 2>&1 | grep pattern

parce qu'il mélangera le STDOUT original et le STDERR.

et celui-ci ne fonctionne pas puisque grep ne lit pas la sortie STDERR:

cmd 1>/dev/null | grep pattern

mais aussi, celui-ci ne marchera pas:

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

parce que la sortie sera complètement vide, puisque tout est écrit /dev/null .

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

52
demandé sur Frank 2009-02-14 23:27:26

3 réponses

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 l'ont précédée sur chaque sortie, de sorte que la sortie du descripteur de fichier de sortie standard (1) d'origine passera à /dev / null, et la sortie du descripteur de fichier d'erreur standard (2) passera à la norme d'origine sortie.

cependant, ce n'est pas comme ça que fonctionne la redirection shell. Chaque redirection fait "remapper" les descripteurs de fichier en fermant la "source" et en dupliquant la "destination" (voir les pages man de dup(2) et close(2) ), dans l'ordre. Cela signifie que dans votre commande la sortie standard est d'abord remplacé par /dev/null , puis d'erreur standard remplacé avec sortie standard, qui est /dev/null déjà.

Ce qui fonctionne:

par conséquent, pour obtenir l'effet désiré, vous avez juste besoin d'inverser les redirections. Ensuite, vous aurez l'erreur standard aller à la sortie standard, et la sortie standard d'origine aller à /dev/null :

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

(notez que le 1 avant > est inutile - 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 quelques autres implémentations font mais pas toutes et il est pas standard ), vous pouvez aussi le faire comme ceci:

cmd 2>&1 >&- | grep pattern

C'est peut-être mieux qu'il peut gagner du temps, parce que lorsque la commande essaie d'écrire sur la sortie standard l'appel à write peut échouer immédiatement sans attendre un commutateur de contexte dans le noyau et le pilote manipulant /dev/null (selon l'implémentation de l'appel système - certains peuvent attraper cela dans la fonction libc , et certains peuvent aussi avoir une manipulation spéciale pour /dev/null ). S'il ya beaucoup de sortie qui peut être utile, et il est plus rapide à taper.

cela fonctionnera principalement parce que la plupart des programmes ne se soucient pas s'ils ne parviennent pas à écrire à la sortie standard (qui vérifie vraiment la valeur de retour de printf ?) et peu importe que la sortie standard soit fermée. Mais certains programmes peuvent se renflouer avec un code d'échec si write échoue - habituellement bloquent les processeurs, les programmes utilisant une bibliothèque soignée pour l'entrée/sortie ou la journalisation à la sortie stdandard. Donc, si cela ne fonctionne pas, rappelez-vous que c'est une cause probable et d'essayer /dev/null .

92
répondu Tom Alsberg 2009-02-14 21:41:28

Fermer STDOUT premier:

1>&-, >&-

voir ici .

2
répondu Charlie Martin 2009-02-14 20:31:32

j'essaierais quelque chose de simple comme:

cmd 2> tmp_file && cat tmp_file | grep pattern && rm -f tmp_file
-4
répondu Martin Cote 2009-02-14 20:33:36