Considérons cet extrait:
stop () {
echo "${1}" 1>&2
exit 1
}
func () {
if false; then
echo "foo"
else
stop "something went wrong"
fi
}
Normalement, lorsque func
est appelé, cela entraînera la terminaison du script, qui est le comportement prévu. Cependant, si elle est exécutée dans une sous-coquille, telle que dans
result=`func`
il ne quittera pas le script. Cela signifie que le code d'appel doit vérifier l'état de sortie de la fonction à chaque fois. Y a-t-il un moyen d'éviter cela? Est-ce quoi set -e
est pour?
Vous pourrait tuer la coque d'origine (kill $$
) Avant d'appeler exit
, et cela fonctionnerait probablement. Mais:
Au lieu de cela, vous pouvez utiliser l'un des plusieurs façons de transmettre une valeur dans la FAQ Bash . La plupart d'entre eux ne sont pas si géniaux, malheureusement. Vous pouvez simplement être bloqué vérifier des erreurs après chaque appel de fonction ( -e
a beaucoup de problèmes ). Soit cela, soit passer à Perl.
Vous pouvez décider que le statut de sortie 77 par exemple signifie quitter n'importe quel niveau de sous-vase et faire
set -E
trap '[ "$?" -ne 77 ] || exit 77' ERR
(
echo here
(
echo there
(
exit 12 # not 77, exit only this subshell
)
echo ici
exit 77 # exit all subshells
)
echo not here
)
echo not here either
set -E
En combinaison avec ERR
Traps est un peu comme une version améliorée de set -e
En ce qu'elle vous permet de définir votre propre manipulation d'erreurs.
Dans ZSH, les pièges ERR sont hérités automatiquement, de sorte que vous n'avez pas besoin de set -E
, Vous pouvez également définir des pièges sous forme TRAPERR()
fonctions et les modifier via $functions[TRAPERR]
, Comme functions[TRAPERR]="echo was here; $functions[TRAPERR]"
Comme une alternative à kill $$
, vous pouvez aussi essayer kill 0
, cela fonctionnera dans le cas des sous-espaces imbriqués (tous les appelants et processus secondaires recevront le signal) ... mais c'est toujours brutal et moche.
(Bash Réponse spécifique) Bash n'a aucun concept d'exception. Toutefois, avec Set -o Errexit (ou l'équivalent: Set -e) au niveau ultime, la commande défaillante entraînera le sous-groupe sortant d'un statut de sortie non nul. S'il s'agit d'un ensemble de sous-vases imbriquées sans conditionnels autour de l'exécution de ces sous-vases, il "roulera efficacement" tout le script et la sortie.
Cela peut être difficile lorsque vous essayez d'inclure des bits de divers codes Bash dans un script plus grand. Un morceau de bash peut fonctionner juste bien seul, mais lorsqu'il est exécuté sous Errexit (ou sans errexit), se comporter de manière inattendue.
[.____] [192.168.13.16 (F0F5E19E) ~ 22:58:22] # Bash -o Errexit /tmp/foo Something a mal tourné [.____ : 58: 31] # Bash /tmp/foo Something a mal tourné Mais nous sommes arrivés ici quand même [192.168.13.16 (f0f5E19e) ~ 22:58:37] # /tmp/foo #!/bin/bash Stop () { echo "$ {1}" } [.____] si faux; alors [.____] echo "foo" [.____] [.____] ([.____] ( STOP "Quelque chose s'est mal passé" [ de toute façon " fi [.____] [192.168.13.16 (f0f5e19e) ~ 22:58:40] #
Essaye ça ...
stop () {
echo "${1}" 1>&2
exit 1
}
func () {
if $1; then
echo "foo"
else
stop "something went wrong"
fi
}
echo "Shell..."
func $1
echo "subshell..."
result=`func $1`
echo "Shell..."
echo "result=$result"
Les résultats que je reçois sont ...
# test_exitsubshell true
Shell...
foo
subshell...
Shell...
result=foo
# test_exitsubshell false
Shell...
something went wrong
Remarques
if
_ tester true
ou false
(voir les 2 exécutions)if
est false
, nous n'atteignons jamais le sous-groupe.