Question

J'ai un script shell qui exécute un certain nombre de commandes. Comment faire en sorte que le script shell se ferme si l’une des commandes se termine avec un code de sortie non nul?

Était-ce utile?

La solution

Après chaque commande, le code de sortie se trouve dans la variable $? afin que vous obteniez quelque chose comme:

ls -al file.ext
rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi

Vous devez faire attention aux commandes piped car le $? ne vous donne que le code de retour du dernier élément du tube donc, dans le code:

ls -al file.ext | sed 's/^/xx: /"

ne renverra pas de code d'erreur si le fichier n'existe pas (car la partie sed du pipeline fonctionne réellement et renvoie 0).

Le shell bash fournit en fait un tableau qui peut être utile dans ce cas, sous la forme PIPESTATUS . Ce tableau comporte un élément pour chacun des composants du pipeline, auquel vous pouvez accéder individuellement, comme $ {PIPESTATUS [0]} :

pax> false | true ; echo ${PIPESTATUS[0]}
1

Notez que vous obtenez le résultat de la commande false , et non le pipeline entier. Vous pouvez également obtenir la liste complète à traiter comme bon vous semble:

pax> false | true | false; echo ${PIPESTATUS[*]}
1 0 1

Si vous souhaitez obtenir le code d'erreur le plus volumineux à partir d'un pipeline, vous pouvez utiliser quelque chose du type:

true | true | false | true | false
rcs=${PIPESTATUS[*]}; rc=0; for i in ${rcs}; do rc=$(($i > $rc ? $i : $rc)); done
echo $rc

Ceci parcourt chacun des éléments PIPESTATUS , en le stockant dans rc s'il était supérieur à la valeur rc précédente. <

Autres conseils

Si vous voulez travailler avec $ ?, vous devrez le vérifier après chaque commande, puisque $? est mis à jour après chaque commande. Cela signifie que si vous exécutez un pipeline, vous n'obtiendrez que le code de sortie du dernier processus du pipeline.

Une autre approche consiste à faire ceci:

set -e
set -o pipefail

Si vous mettez ceci en haut du script shell, il semble que bash s’occupe de cela pour vous. Comme l'a noté une affiche précédente, " set -e " provoquera la fermeture de bash avec une erreur sur une commande simple. "set -o pipefail" bash se ferme avec une erreur sur n'importe quelle commande d'un pipeline.

Voir ici ou ici pour un peu plus de discussion sur ce problème. Voici la section du manuel bash sur le plateau construit.

& définir -e " est probablement le moyen le plus simple de le faire. Il suffit de mettre cela avant toute commande dans votre programme.

Si vous appelez simplement exit dans le bash sans paramètre, le code de sortie de la dernière commande sera renvoyé. Combinée à OR, la bash ne doit appeler l'exit que si la commande précédente échoue. Mais je n'ai pas testé cela.

command1 || exit;
command2 || exit;

Le Bash stockera également le code de sortie de la dernière commande dans la variable $?.

[ $? -eq 0 ] || exit $?; # exit for none-zero return code

http://cfaj.freeshell.org/shell/cus- faq-2.html # 11

  1. Comment obtenir le code de sortie de cmd1 dans cmd1 | cmd2

    Tout d'abord, notez que le code de sortie cmd1 peut être différent de zéro et qu'il n'en est toujours pas. signifie une erreur. Cela se produit par exemple dans

    cmd | head -1
    

    vous pouvez observer un état de sortie 141 (ou 269 avec ksh93) de cmd1 , mais c'est parce que cmd a été interrompu par un signal SIGPIPE lorsque head -1 s'est terminé après avoir lu une ligne.

    Pour connaître l'état de sortie des éléments d'un pipeline cmd1 | cmd2 | cmd3

    a. avec zsh:

    Les codes de sortie sont fournis dans le tableau spécial pipestatus.    Le code de sortie cmd1 est dans $ pipestatus [1] , cmd3 code de sortie dans     $ pipestatus [3] , de sorte que $? est toujours identique à     $ pipestatus [-1] .

    b. avec bash:

    Les codes de sortie sont fournis dans le tableau spécial PIPESTATUS .    Le code de sortie cmd1 est dans $ {PIPESTATUS [0]} , cmd3 code de sortie dans     $ {PIPESTATUS [2]} , de sorte que $? est toujours identique à     $ {PIPESTATUS: -1} .

    ...

    Pour plus de détails, voir le lien suivant.

pour bash:

# this will trap any errors or commands with non-zero exit status
# by calling function catch_errors()
trap catch_errors ERR;

#
# ... the rest of the script goes here
#  

function catch_errors() {
   # do whatever on errors
   # 
   #
   echo "script aborted, because of errors";
   exit 0;
}

Pour cela, rien de plus simple, associez-les simplement avec & amp; & amp;:

.
command1 && command2 && command3

Vous pouvez également utiliser la construction imbriquée de if:

if command1
   then
       if command2
           then
               do_something
           else
               exit
       fi
   else
       exit
fi
#
#------------------------------------------------------------------------------
# run a command on failure exit with message
# doPrintHelp: doRunCmdOrExit "$cmd"
# call by:
# set -e ; doRunCmdOrExit "$cmd" ; set +e
#------------------------------------------------------------------------------
doRunCmdOrExit(){
    cmd="$@" ;

    doLog "DEBUG running cmd or exit: \"$cmd\""
    msg=$($cmd 2>&1)
    export exit_code=$?

    # if occured during the execution exit with error
    error_msg="Failed to run the command:
        \"$cmd\" with the output:
        \"$msg\" !!!"

    if [ $exit_code -ne 0 ] ; then
        doLog "ERROR $msg"
        doLog "FATAL $msg"
        doExit "$exit_code" "$error_msg"
    else
        #if no errors occured just log the message
        doLog "DEBUG : cmdoutput : \"$msg\""
        doLog "INFO  $msg"
    fi

}
#eof func doRunCmdOrExit
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top