2 votes

Renvoyer automatiquement le script `source` en cas d'échec de la commande

Comment puis-je faire en sorte qu'un script source revienne automatiquement s'il échoue à une commande à l'intérieur?

Supposons que j'ai un script qui se termine automatiquement en cas d'échec avec set -e, par exemple.

#!/bin/bash
# foo.env
set -e        # sortie automatique en cas d'échec de n'importe quelle commande
echo "salut"
grep 123 456  # cette commande échouera (je n'ai pas de fichier nommé "456")
echo "ne devrait pas arriver ici"

Si j'exécute la commande normalement, elle se termine automatiquement sur la commande grep en échec :

box1% ./foo.env
salut
grep: 456: Aucun fichier ou dossier de ce type

Cependant, si je source le script, il sort de mon shell courant, pas seulement du script en cours de sourçage :

box1% ssh box2
box2% source ./foo.env
salut
grep: 456: Aucun fichier ou dossier de ce type
Connection to box2 closed.
box1%

Si je supprime le set -e,

#!/bin/bash
# foo2.env
echo "salut"
grep 123 456  # cette commande échouera (je n'ai pas de fichier nommé "456")
echo "ne devrait pas arriver ici"

alors il ne se termine pas automatiquement ou ne revient pas automatiquement au script source :

box1% ssh box2
box2% source ./foo2.env
salut
grep: 456: Aucun fichier ou dossier de ce type
ne devrait pas arriver ici
box2%

La seule solution de contournement que j'ai trouvée jusqu'à présent est d'ajouter une expression return à chaque ligne de code dans le script, par exemple :

box1% cat foo3.env
#!/bin/bash
# foo3.env - fonctionne, mais est fastidieux
echo "salut" || return
grep 123 456 || return
echo "ne devrait pas arriver ici" || return

box1% source foo3.env
salut
grep: 456: Aucun fichier ou dossier de ce type
box1%

Y a-t-il une autre façon pour les scripts source, similaire à la façon dont set -e fonctionne pour ceux qui ne sont pas source?

1voto

Hastur Points 17791

Lorsque vous source un script, c'est comme si vous écriviez ce fichier ligne par ligne depuis le clavier. Cela signifie que set -e considérera l'environnement shell actuel et en cas d'erreur, il quittera ce shell actuel.

C'est une solution de contournement. Aujourd'hui, je me sens paresseux donc j'ai pensé que l'ordinateur peut écrire ||return pour moi, ou mieux lire le fichier ligne par ligne et exécuter ainsi :

#!/bin/bash
# c'est le fichier MySource.sh
while IFS='' read -r ligne
do
   [[ $ligne == \#* ]] || $ligne || return
done < "$1"

exécutez-le avec . MySource.sh FichierASourcer.sh

Si votre script FichierASourcer.sh contient des commandes sur une seule ligne, cela devrait fonctionner.
Encore loin d'être prêt à être utilisé dans un environnement de production.
Testez-le et éventuellement utilisez-le à vos propres risques.

Il saute les lignes qui commencent par # car elles devraient provoquer l'erreur # commande introuvable.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X