Le Linux set
et pipefail
Les commandes dictent ce qui se passe lorsqu’un échec se produit dans un script Bash. Il y a plus à penser que cela devrait-il s’arrêter ou devrait-il continuer.
EN RELATION: Le guide du débutant pour les scripts shell : les bases
Scripts bash et conditions d’erreur
Les scripts shell bash sont excellents. Ils sont rapides à écrire et n’ont pas besoin d’être compilés. Toute action répétitive ou en plusieurs étapes que vous devez effectuer peut être intégrée dans un script pratique. Et comme les scripts peuvent appeler n’importe quel utilitaire Linux standard, vous n’êtes pas limité aux capacités du langage shell lui-même.
Mais des problèmes peuvent survenir lorsque vous appelez un utilitaire ou un programme externe. S’il échoue, l’utilitaire externe se fermera et enverra un code de retour au shell, et il pourrait même imprimer un message d’erreur au terminal. Mais votre script continuera à être traité. Ce n’est peut-être pas ce que vous vouliez. Si une erreur se produit au début de l’exécution du script, cela peut aggraver les problèmes si le reste du script est autorisé à s’exécuter.
Vous pouvez vérifier le code de retour de chaque processus externe à mesure qu’il se termine, mais cela devient difficile lorsque les processus sont redirigés vers d’autres processus. Le code de retour proviendra du processus à la fin du tube, et non de celui du milieu qui a échoué. Bien sûr, des erreurs peuvent également se produire à l’intérieur de votre script, comme essayer d’accéder à une variable non initialisée.
le set
et pipefile
Les commandes vous permettent de décider ce qui se passe lorsque des erreurs comme celles-ci se produisent. Ils vous permettent également de détecter les erreurs même lorsqu’elles se produisent au milieu d’une chaîne de tuyaux.
Voici comment les utiliser.
Démonstration du problème
Voici un script Bash trivial. Il renvoie deux lignes de texte au terminal. Vous pouvez exécuter ce script si vous copiez le texte dans un éditeur et l’enregistrez sous « script-1.sh ».
#!/bin/bash echo This will happen first echo This will happen second
Pour le rendre exécutable, vous devrez utiliser chmod
:
chmod +x script-1.sh
Vous devrez exécuter cette commande sur chaque script si vous souhaitez les exécuter sur votre ordinateur. Exécutons le script :
./script-1.sh
Les deux lignes de texte sont envoyées à la fenêtre du terminal comme prévu.
Modifions légèrement le script. Nous demanderons ls
pour lister les détails d’un fichier qui n’existe pas. Cela échouera. Nous l’avons enregistré sous le nom de « script-2.sh » et l’avons rendu exécutable.
#!/bin/bash echo This will happen first ls imaginary-filename echo This will happen second
Lorsque nous exécutons ce script, nous voyons le message d’erreur de ls
.
./script-2.sh
Bien que le ls
La commande a échoué, le script a continué à s’exécuter. Et même s’il y a eu une erreur lors de l’exécution du script, le code de retour du script au shell est zéro, ce qui indique un succès. Nous pouvons vérifier cela en utilisant echo et le $?
variable qui contient le dernier code de retour envoyé au shell.
echo $?
Le zéro qui est signalé est le code de retour du deuxième écho du script. Il y a donc deux problèmes avec ce scénario. Le premier est que le script a eu une erreur mais qu’il a continué à s’exécuter. Cela peut entraîner d’autres problèmes si le reste du script attend ou dépend de l’action qui a échoué et qui a effectivement réussi. Et la seconde est que si un autre script ou processus a besoin de vérifier le succès ou l’échec de ce script, il obtiendra une fausse lecture.
L’option set -e
le set -e
(exit) provoque la sortie d’un script si l’un des processus qu’il appelle génère un code retour différent de zéro. Tout ce qui n’est pas nul est considéré comme un échec.
En ajoutant le set -e
option au début du script, nous pouvons modifier son comportement. Il s’agit de « script-3.sh ».
#!/bin/bash set -e echo This will happen first ls imaginary-filename echo This will happen second
Si nous exécutons ce script, nous verrons l’effet de set -e
.
./script-3.sh
echo $?
Le script est arrêté et le code de retour envoyé au shell est une valeur non nulle.
Faire face aux défaillances dans les tuyaux
La tuyauterie ajoute plus de complexité au problème. Le code de retour qui sort d’une séquence de commandes canalisée est le code de retour de la dernière commande de la chaîne. S’il y a un échec avec une commande au milieu de la chaîne, nous revenons à la case départ. Ce code de retour est perdu et le script poursuivra le traitement.
Nous pouvons voir les effets des commandes de tuyauterie avec différents codes de retour en utilisant le true
et false
intégrés au shell. Ces deux commandes ne font que générer un code de retour de zéro ou un, respectivement.
true
echo $?
false
echo $?
Si on pipe false
dans true
-avec false
représentant un processus défaillant – nous obtenons true
le code de retour de zéro.
false | true
echo $?
Bash a une variable tableau appelée PIPESTATUS
et cela capture tous les codes de retour de chaque programme de la chaîne de canaux.
false | true | false | true
echo "$PIPESTATUS[0] $PIPESTATUS[1] $PIPESTATUS[2] $PIPESTATUS[3]"
PIPESTATUS
ne contient que les codes de retour jusqu’à ce que le programme suivant s’exécute, et essayer de déterminer quel code de retour va avec quel programme peut devenir très désordonné très rapidement.
C’est ici que set -o
(choix) et pipefail
Entrez. C’est « script-4.sh ». Cela essaiera de canaliser le contenu d’un fichier qui n’existe pas dans wc
.
#!/bin/bash set -e echo This will happen first cat script-99.sh | wc -l echo This will happen second
Cela échoue, comme on pouvait s’y attendre.
./script-4.sh
echo $?
Le premier zéro est la sortie de wc
, nous indiquant qu’il n’a lu aucune ligne pour le fichier manquant. Le deuxième zéro est le code de retour du deuxième echo
commander.
Nous ajouterons dans le -o pipefail
enregistrez-le sous « script-5.sh » et rendez-le exécutable.
#!/bin/bash set -eo pipefail echo This will happen first cat script-99.sh | wc -l echo This will happen second
Exécutons cela et vérifions le code de retour.
./script-5.sh
echo $?
Le script s’arrête et la seconde echo
la commande n’est pas exécutée. Le code de retour envoyé au shell est un, indiquant correctement un échec.
EN RELATION: Comment utiliser la commande Echo sous Linux
Attraper des variables non initialisées
Les variables non initialisées peuvent être difficiles à repérer dans un script réel. Si nous essayons de echo
la valeur d’une variable non initialisée, echo
imprime simplement une ligne vierge. Il ne génère pas de message d’erreur. Le reste du script continuera à s’exécuter.
Il s’agit de script-6.sh.
#!/bin/bash set -eo pipefail echo "$notset" echo "Another echo command"
Nous allons l’exécuter et observer son comportement.
./script-6.sh
echo $?
Le script parcourt la variable non initialisée et continue de s’exécuter. Le code de retour est zéro. Essayer de trouver une erreur comme celle-ci dans un script très long et compliqué peut être très difficile.
Nous pouvons piéger ce type d’erreur en utilisant le set -u
(non défini). Nous allons l’ajouter à notre collection croissante d’options set en haut du script, l’enregistrer sous « script-7.sh » et le rendre exécutable.
#!/bin/bash set -eou pipefail echo "$notset" echo "Another echo command"
Exécutons le script :
./script-7.sh
echo $?
La variable non initialisée est détectée, le script s’arrête et le code de retour est défini sur un.
le -u
(non défini) l’option est suffisamment intelligente ne pas être déclenché par des situations où vous pouvez légitimement interagir avec une variable non initialisée.
Dans « script-8.sh », le script vérifie si la variable New_Var
est initialisé ou non. Vous ne voulez pas que le script s’arrête ici, dans un script du monde réel, vous effectuerez un traitement supplémentaire et gérerez la situation vous-même.
Notez que nous avons ajouté le -u
option comme le seconde option dans l’instruction set. le -o pipefail
l’option doit venir en dernier.
#!/bin/bash set -euo pipefail if [ -z "$New_Var:-" ]; then echo "New_Var has no value assigned to it." fi
Dans « script-9.sh », la variable non initialisée est testée et si elle n’est pas initialisée, une valeur par défaut est fournie à la place.
#!/bin/bash set -euo pipefail default_value=484 Value=$New_Var:-$default_value echo "New_Var=$Value"
Les scripts sont autorisés à s’exécuter jusqu’à leur achèvement.
./script-8.sh
./script-9.sh
Scellé à la hache
Une autre option pratique à utiliser est la set -x
(exécuter et imprimer). Lorsque vous écrivez des scripts, cela peut vous sauver la vie. il imprime les commandes et leurs paramètres au fur et à mesure de leur exécution.
Il vous donne une forme de trace d’exécution rapide et prête à l’emploi. Isoler les failles logiques et repérer les bogues devient beaucoup, beaucoup plus facile.
Nous allons ajouter l’option set -x à « script-8.sh », l’enregistrer sous « script-10.sh » et le rendre exécutable.
#!/bin/bash set -euxo pipefail if [ -z "$New_Var:-" ]; then echo "New_Var has no value assigned to it." fi
Exécutez-le pour voir les lignes de trace.
./script-10.sh
Repérer les bogues dans ces exemples de scripts triviaux est facile. Lorsque vous commencerez à écrire des scripts plus complexes, ces options feront leurs preuves.