Comment puis-je rediriger STDERR vers STDOUT, mais ignorer le STDOUT original? [dupliquer]
cette question a déjà une réponse ici:
- comment pipe stderr, et non stdout? 10 réponses
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?
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
.
j'essaierais quelque chose de simple comme:
cmd 2> tmp_file && cat tmp_file | grep pattern && rm -f tmp_file