Comment désactiver set -e pour une commande individuelle?


36

La commande set -e fait échouer un script bash immédiatement lorsqu'une commande renvoie un code de sortie différent de zéro.

  1. Existe-t-il un moyen simple et élégant de désactiver ce comportement pour une commande individuelle dans un script?

  2. À quels endroits cette fonctionnalité est-elle documentée dans le manuel de référence de Bash ( http://www.gnu.org/software/bash/manual/bashref.html )?

Réponses:


29
  1. Quelque chose comme ça:

    #!/usr/bin/env bash
    
    set -e
    echo hi
    
    # disable exitting on error temporarily
    set +e
    aoeuidhtn
    echo next line
    
    # bring it back
    set -e
    ao
    
    echo next line

    Courir:

    $ ./test.sh
    hi
    ./test.sh: line 7: aoeuidhtn: command not found
    next line
    ./test.sh: line 11: ao: command not found
  2. Il est décrit dans l' setaide intégrée:

    $ type set
    set is a shell builtin
    $ help set
    (...)
    Using + rather than - causes these flags to be turned off.

La même chose est documentée ici: https://www.gnu.org/software/bash/manual/bashref.html#The-Set-Builtin .


Merci! J'ai trouvé une autre possibilité: #! / Bin / bash set -e # Décommente la ligne suivante pour voir l'effet set -e: #blubb if blubb; puis écho "La commande blubb a réussi." sinon echo "La commande blubb a échoué. Code de sortie: $?" fi echo normal script exit
Gustave

22

Une alternative à la suppression de la caution en cas d'erreur serait de forcer le succès quoi qu'il arrive. Vous pouvez faire quelque chose comme ça:

cmd_to_run || true

Cela retournera 0 (vrai), donc l'ensemble -e ne devrait pas être déclenché


3
faulty_cmd || :est un autre idiome populaire pour cela. (Il :s'agit également d'une commande true).
ulidtko

3
@ulidtko - intéressant.
M'a conduit dans

12

Si vous essayez d'attraper le code retour / erreur (fonction ou fork), cela fonctionne:

function xyz {
    return 2
}

xyz && RC=$? || RC=$?

8

Si l'option "Quitter immédiatement le shell" s'applique ou est ignorée, cela dépend du contexte de la commande exécutée (voir la section Bash Reference Manual sur le Set Builtin - grâce à Arkadiusz Drabczyk).

En particulier, l'option est ignorée si une commande fait partie du test dans une instruction if. Par conséquent, il est possible d'exécuter une commande et de vérifier son succès ou son échec dans un "contexte de sortie immédiate" à l'aide d'une instruction if comme celle-ci:

#!/bin/bash

set -e

# Uncomment next line to see set -e effect:
#blubb

if blubb; then
  echo "Command blubb was succesful."
else 
  echo "Command blubb failed. Exit code: $?"
fi
echo "Script exited normally."

Il est possible d'omettre l'instruction "then" et d'utiliser moins de lignes:

if blubb; then :;
else echo "Command blubb failed. Exit code: $?"; fi

2

Une autre approche, que je trouve assez simple (et qui s'applique à d'autres setoptions en plus de -e):

Utilisez $-pour restaurer les paramètres.

Par exemple:

oldopt=$-
set +e
# now '-e' is definitely disabled.
# do some stuff...

# Restore things back to how they were
set -$oldopt

Bien que -espécifiquement, les options que d'autres ont évoquées ( || trueou «mises à l'intérieur d'un if») peuvent être plus idiomatiques.


0

J'ai en fait posé une question similaire récemment (même si je n'ai pas posté, j'y suis allé), et, d'après ce que je peux voir, il semble que simplement utiliser set + e avant la commande et set -e par la suite fonctionne le plus élégamment. Voici un exemple, saisissant la réponse de la commande et ne laissant pas l'erreur la jeter.

#!/bin/sh

args=""
for argcol in $*
do
    args="${args} ${argcol}"
done
fortunevar=""
fortfail=""
{
    set +e
    fortunevar=`fortune $args`
    fortfail=$?
    set -e
} &> /dev/null
if [ $fortfail == 0 ]
then
    echo ${fortunevar}
    say ${fortunevar}
else
    echo misfortune: an illegal option was detected!
    echo misfortune: usage: misfortune [-afilosw] [-m pattern][ [#%] file/directory/all]
fi

Cela saisit la sortie de «fortune», vérifie son statut de sortie, fait écho et le dit. Je pense que c'est ce que vous demandiez, ou du moins quelque chose de similaire? Quoi qu'il en soit, j'espère que cela vous aidera.


Pour clarifier, le bit entre parenthèses bouclés étant redirigé vers / dev / null est ce que vous recherchez, je crois. Il rend la commande sans sortie et vérifie son état d'erreur sans quitter le programme.
Addison Crump

0

J'aime démarrer le sous-shell si je veux changer quelque chose temporairement. La commande ci-dessous montre que la première bad_command est ignorée et la seconde abandonne l'exécution.

bash -c 'set -e ;\
( set +e; bad_command ; echo still here ) ;\
echo even here ; \
bad_command ; \
echo but not here;'
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.