J'ai un programme dont la sortie de STDERR
je veux inspecter et exécuter grep
sur etc.
Je pouvais donc le rediriger vers STDOUT
et utiliser grep, mais le problème est que je pas veux le contenu STDOUT
d'origine.
Donc, celui-ci ne fera pas
cmd 2>&1 | grep pattern
car il mélangera le STDOUT et le STDERR d'origine.
Et celui-ci ne fonctionne pas car grep ne lit pas la sortie STDERR:
cmd 1>/dev/null | grep pattern
Mais aussi, celui-ci ne fonctionnera pas:
cmd 1>/dev/null 2>&1 | grep pattern
car la sortie sera complètement vide, car tout est écrit dans /dev/null
.
Mais il doit y avoir un moyen simple de le faire?
La raison pour laquelle la dernière commande que vous avez citée:
cmd 1>/dev/null 2>&1 | grep pattern
ne fonctionne pas, découle 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 le précèdent sur chaque sortie, de sorte que la sortie du descripteur de fichier de sortie standard d'origine (1) ira vers/dev/null, et la sortie vers le descripteur de fichier d'erreur standard (2) sera aller à la sortie standard d'origine.
Cependant, ce n'est pas ainsi que fonctionne la redirection Shell. Chaque redirection entraîne le "remappage" des descripteurs de fichiers en fermant la "source" et en dupliquant la "destination" (voir les pages man
de dup(2)
et close(2)
), en ordre. Cela signifie que dans votre commande, la sortie standard est d'abord remplacée par /dev/null
, Puis l'erreur standard est remplacée par la sortie standard, qui est déjà /dev/null
.
Par conséquent, pour obtenir l'effet souhaité, il vous suffit 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 1
avant >
n'est pas nécessaire - pour la redirection de 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 prend en charge cette extension (bash
et certaines autres implémentations le font mais pas toutes et c'est non standard ), vous pouvez également le faire comme ceci:
cmd 2>&1 >&- | grep pattern
Cela peut être mieux - cela peut 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 le pilote gérant /dev/null
(selon l'implémentation de l'appel système - certains peuvent intercepter cela dans la fonction libc
, et certains peuvent également avoir une gestion spéciale pour /dev/null
). S'il y a beaucoup de sorties qui peuvent valoir la peine, et c'est plus rapide à taper.
Cela fonctionnera principalement parce que la plupart des programmes ne se soucient pas s'ils n'écrivent pas sur la sortie standard (qui vérifie vraiment la valeur de retour de printf
?) Et ne se soucieront pas que la sortie standard soit fermée. Mais certains programmes peuvent renflouer avec un code d'échec si write
échoue - bloquent généralement les processeurs, les programmes utilisant une bibliothèque soignée pour les E/S ou se connectant à la sortie standard. Donc, si cela ne fonctionne pas, souvenez-vous que c'est une cause probable et essayez /dev/null
.