Question

Je suis un noob en shell-script. Je veux imprimer un message et sortir d'un script si une commande échoue. J'ai essayé:

my_command && (echo 'my_command failed; exit)

mais il ne fonctionne pas. Il garde d'exécuter les instructions ci-dessous cette ligne dans le script. J'utilise Ubuntu et bash.

Était-ce utile?

La solution

Essayez:

my_command || { echo 'my_command failed' ; exit 1; }

Quatre changements:

  • Modifier && à ||
  • Utiliser { } en place de ( )
  • Présentez ; après exit et
  • espaces après { et avant }

Puisque vous voulez imprimer le message et la sortie que lorsque la commande échoue (sorties avec une valeur non nulle) dont vous avez besoin d'un || pas &&.

cmd1 && cmd2

se déroulera lorsque cmd2 cmd1 réussit (valeur de sortie 0). Où que

cmd1 || cmd2

exécutera cmd2 lorsque cmd1 échoue (la valeur de sortie non nul).

Utilisation ( ) fait la commande à l'intérieur de les exécuter dans un sous-shell et appeler un exit à partir de là vous fait sortir du sous-shell et non votre coquille d'origine, par conséquent, l'exécution se poursuit dans votre shell d'origine.

Pour remédier à cette utilisation { }

Les deux derniers changements sont nécessaires par bash.

Autres conseils

Les autres réponses ont couvert la question directe bien, mais vous pouvez aussi être intéressé à utiliser set -e. Avec cela, toute commande qui échoue (en dehors des contextes spécifiques tels que des tests de if) provoquera le script pour abandonner. Pour certains scripts, il est très utile.

Si vous voulez que le comportement pour toutes les commandes dans votre script, il suffit d'ajouter

  set -e 
  set -o pipefail

au début du script. Cette paire d'options dire l'interpréteur bash pour quitter chaque fois qu'un commande retourne avec un code de sortie non nul.

Cela ne vous permet pas d'imprimer un message de sortie, cependant.

Notez également, l'état de sortie de chaque commande est stockée dans la variable shell $ ?, que vous pouvez vérifier immédiatement après l'exécution de la commande. Un état de non-zéro indique l'échec:

my_command
if [ $? -eq 0 ]
then
    echo "it worked"
else
    echo "it failed"
fi

J'ai piraté le langage suivant:

echo "Generating from IDL..."
idlj -fclient -td java/src echo.idl
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi

echo "Compiling classes..."
javac *java
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi

echo "Done."

précéder chaque commande un écho informatif, et suivez chaque commande avec ce même
 ligne if [ $? -ne 0 ];.... (Bien sûr, vous pouvez modifier ce message d'erreur si vous voulez.)

est fourni my_command canoniquement conçu, ie renvoie 0 quand réussit, && est exactement le contraire de ce que vous voulez. Vous voulez ||.

Notez également que ( ne semble pas juste pour moi en bash, mais je ne peux pas essayer d'où je suis. Dites-moi.

my_command || {
    echo 'my_command failed' ;
    exit 1; 
}

Vous pouvez également utiliser, si vous souhaitez conserver le statut d'erreur de sortie, et un fichier lisible avec une commande par ligne:

my_command1 || exit $?
my_command2 || exit $?

, mais n'imprimera aucun message d'erreur supplémentaire. Mais dans certains cas, l'erreur sera imprimé par la commande n'a pas pu de toute façon.

La coquille de trap intégrée permet la capture de signaux, et d'autres conditions utiles, y compris l'exécution de la commande qui a échoué (à savoir, un état de retour non nul). Donc, si vous ne voulez pas l'état de retour de test explicitement de chaque commande, vous pouvez dire trap "your shell code" ERR et le code shell seront exécutées chaque fois qu'un commande retourne un statut non nul. Par exemple:

trap "echo script failed; exit 1" ERR

Notez que comme pour les autres cas de commandes de capture ont échoué, les pipelines ont besoin d'un traitement spécial; ci-dessus ne sera pas prise false | true.

Les fonctions suivantes ne erreurs échos si une commande échoue:

silently () {
    label="${1}"
    command="${2}"
    error=$(eval "${command}" 2>&1 >"/dev/null")

    if [ ${?} -ne 0 ]; then
        echo "${label}: ${error}" >&2
        exit 1
    fi
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top