2010-09-03 3 views
17

Je dois capturer la sortie et l'erreur d'une commande dans mon script bash et savoir si la commande a réussi ou non.bash variable capturer stderr et stdout séparément ou obtenir la valeur de sortie

Au moment, je capturant les deux comme ceci:

output=$(mycommand 2>&1) 

Il me faut ensuite vérifier la valeur de sortie de mycommand. Si elle échoue, j'ai besoin de faire quelque chose avec la sortie, si la commande réussit, je n'ai pas besoin de toucher la sortie.

Puisque je capture la sortie, cochez $? est toujours un 0 puisque bash a réussi à capturer la sortie dans la variable.

Ceci est un moment très manuscrit sensible, donc nous essayons d'éviter des solutions plus lentes comme la sortie vers un fichier et re-lecture dans.

Si je pouvais capturer stdout à une variable et stderr à un autre, cela résoudrait mon problème car je pourrais juste vérifier si la variable d'erreur était vide ou non.

Merci.

+4

Voir [BashFAQ/002] (http://mywiki.wooledge.org/BashFAQ/002) et [BashFAQ/047] (http://mywiki.wooledge.org/BashFAQ/047). –

Répondre

8

Quelle version de bash utilisez-vous? La capture de la sortie a zéro effet sur le code de retour avec ma version, 4.1.5:

pax> false; echo $? 
1 
pax> echo $? 
0 
pax> x=$(false 2>&1) ; echo $? 
1 

Ce n'est pas toujours une bonne idée de compter sur l'erreur standard étant de détecter les erreurs non vide. De nombreux programmes ne génèrent pas d'erreurs mais s'appuient sur uniquement sur le code de retour.

+0

J'ai oublié de mentionner que je redirige la sortie de ma commande vers une autre. Bien que je puisse le faire après les sorts dans une commande séparée. Merci. – mhost

+3

Attention! Ayant 'local x = $ (faux 2> &1) ; echo $?' Ou 'set x = $ (faux 2> &1) ; echo $?' (Notez ** 'local/set' ** au debut) renvoie' 0' non '1' étant donné que la dernière commande est' local/set' –

10

Le problème ne semble se manifester lorsque la sortie est capturée à une variable locale dans une fonction:

$ echo $BASH_VERSION 
3.2.48(1)-release 
$ false; echo $? 
1 
$ echo $? 
0 
$ x=$(false 2>&1) ; echo $? 
1 
$ function f { 
> local x=$(false 2>&1) ; echo $? 
> } 
$ f 
0 
$ function g { 
> x=$(false 2>&1) ; echo $? 
> } 
$ g 
1 

Notez que la seule fonction f, qui capte x à un local, peut exprimer le comportement. En particulier, la fonction g qui fait la même chose, mais sans le mot clé 'local', fonctionne.

On ne peut donc pas utiliser une variable locale, et peut-être la 'désactiver' après utilisation.

EDIT souligne NVRAM que la déclaration locale peut être faite au préalable pour éviter la question:

$ function h { 
> local x 
> x=$(false 2>&1) ; echo $? 
> } 
$ h 
1 
+0

Très intéressant! Cela se produit aussi bien dans bash que dans le shell dash (posix) – Gregor

+3

En fait $ $ est défini pour la déclaration de variable locale, si vous le déclarez simplement par lui-même, alors, assignez-le sur une ligne distincte, il fonctionnera comme vous voulez.En d'autres termes, ajoutez ** local x ** au-dessus de votre ligne avec ** x = ** – NVRAM

Questions connexes