Comment intercepter les erreurs dans les scripts Bash sous Linux

fatmawati achmad zaenuri/Shutterstock.com

Par défaut, un script Bash sous Linux signalera une erreur mais continuera à s’exécuter. Nous vous montrons comment gérer vous-même les erreurs afin que vous puissiez décider de ce qui doit se passer ensuite.

Gestion des erreurs dans les scripts

La gestion des erreurs fait partie de la programmation. Même si vous écrivez un code sans faille, vous pouvez toujours rencontrer des conditions d’erreur. L’environnement de votre ordinateur change au fil du temps, à mesure que vous installez et désinstallez des logiciels, créez des répertoires et effectuez des mises à niveau et des mises à jour.

Par exemple, un script qui s’exécutait sans problème peut rencontrer des difficultés si les chemins de répertoire changent ou si les autorisations sont modifiées sur un fichier. L’action par défaut du shell Bash est d’afficher un message d’erreur et de continuer à exécuter le script. C’est un défaut dangereux.

Si l’action qui a échoué est critique pour un autre traitement ou action qui se produit plus tard dans votre script, cette action critique ne réussira pas. À quel point cela s’avère désastreux dépend de ce que votre script essaie de faire.

Un schéma plus robuste détecterait les erreurs et laisserait le script fonctionner s’il devait s’arrêter ou essayer de remédier à la condition de panne. Par exemple, si un répertoire ou un fichier manque, il peut être satisfaisant que le script les recrée.

Si le script a rencontré un problème dont il ne peut pas se remettre, il peut s’arrêter. Si le script doit s’arrêter, il peut avoir la possibilité d’effectuer tout nettoyage requis, comme la suppression de fichiers temporaires ou l’écriture de la condition d’erreur et de la raison de l’arrêt dans un fichier journal.

Détection du statut de sortie

Les commandes et les programmes génèrent une valeur qui est envoyée au système d’exploitation lorsqu’ils se terminent. C’est ce qu’on appelle leur statut de sortie. Il a une valeur de zéro s’il n’y a pas eu d’erreurs, ou une valeur différente de zéro si une erreur s’est produite.

Nous pouvons vérifier l’état de sortie, également appelé code de retour, des commandes utilisées par le script et déterminer si la commande a réussi ou non.

Dans Bash, zéro équivaut à vrai. Si la réponse de la commande est autre que vrai, nous savons qu’un problème s’est produit et nous pouvons prendre les mesures appropriées.

Copiez ce script dans un éditeur et enregistrez-le dans un fichier appelé « bad_command.sh ».

#!/bin/bash

if ( ! bad_command ); then
  echo "bad_command flagged an error."
  exit 1
fi

Vous devrez rendre le script exécutable avec le chmod commande. Il s’agit d’une étape nécessaire pour rendre n’importe quel script exécutable, donc si vous voulez essayer les scripts sur votre propre machine, n’oubliez pas de le faire pour chacun d’eux. Remplacez le nom du script approprié dans chaque cas.

chmod +x bad_command.sh

Rendre un script exécutable en utilisant chmod

Lorsque nous exécutons le script, nous voyons le message d’erreur attendu.

./bad_command.sh

Vérification de l'état de sortie d'une commande pour déterminer s'il y a eu une erreur

Il n’y a pas de commande telle que « bad_command », ni le nom d’une fonction dans le script. Il ne peut pas être exécuté, donc la réponse est ne pas zéro. Si la réponse n’est pas zéro, le point d’exclamation est utilisé ici comme point logique NOT opérateur—le corps du if l’instruction est exécutée.

Dans un script réel, cela pourrait terminer le script, ce que fait notre exemple, ou cela pourrait essayer de remédier à la condition d’erreur.

Cela pourrait ressembler à exit 1 ligne est redondante. Après tout, il n’y a rien d’autre dans le script et il va se terminer de toute façon. Mais en utilisant le exit La commande nous permet de renvoyer un état de sortie au shell. Si jamais notre script est appelé depuis un second script, ce second script saura que ce script a rencontré des erreurs.

Vous pouvez utiliser la logique OR opérateur avec le statut de sortie d’une commande, et appelez une autre commande ou une fonction dans votre script s’il y a une réponse non nulle de la première commande.

command_1 || command_2

Cela fonctionne car soit la première commande s’exécute OR la deuxième. La commande la plus à gauche est exécutée en premier. Si elle réussit, la deuxième commande n’est pas exécutée. Mais si la première commande échoue, la deuxième commande est exécutée. Nous pouvons donc structurer le code comme celui-ci. C’est « logique-or./sh. »

#!/bin/bash

error_handler()

  echo "Error: ($?) $1"
  exit 1


bad_command || error_handler "bad_command failed, Line: $LINENO"

Nous avons défini une fonction appelée error_handler . Cela imprime l’état de sortie de la commande ayant échoué, contenu dans la variable $? et une ligne de texte qui lui est transmise lorsque la fonction est appelée. Ceci est contenu dans la variable $1. La fonction termine le script avec un état de sortie de un.

Le script essaie de s’exécuter bad_command qui échoue évidemment, donc la commande à droite de la logique OR opérateur, ||, est exécuté. Cela appelle le error_handler fonction et passe une chaîne qui nomme la commande qui a échoué et contient le numéro de ligne de la commande qui a échoué.

Nous allons exécuter le script pour voir le message du gestionnaire d’erreurs, puis vérifier l’état de sortie du script à l’aide de echo.

./logical-or.sh
echo $?

Utilisation de l'opérateur logique OU pour appeler le gestionnaire d'erreurs dans un script

Notre petit error_handler la fonction fournit l’état de sortie de la tentative d’exécution bad_command, le nom de la commande et le numéro de ligne. Il s’agit d’informations utiles lorsque vous déboguez un script.

L’état de sortie du script est un. Le statut de sortie 127 signalé par error_handler signifie « commande introuvable ». Si nous le voulions, nous pourrions l’utiliser comme état de sortie du script en le transmettant au exit commande.

Une autre approche consisterait à étendre error_handler pour vérifier les différentes valeurs possibles du statut de sortie et effectuer différentes actions en conséquence, en utilisant ce type de construction :

exit_code=$?

if [ $exit_code -eq 1 ]; then
  echo "Operation not permitted"

elif [ $exit_code -eq 2 ]; then
  echo "Misuse of shell builtins"
.
.
.
elif [ $status -eq 128 ]; then
  echo "Invalid argument"
fi

Utiliser set pour forcer une sortie

Si vous savez que vous voulez que votre script se termine chaque fois qu’il y a une erreur, vous pouvez le forcer à le faire. cela signifie que vous renoncez à tout nettoyage – ou à tout autre dommage également – car votre script se termine dès qu’il détecte une erreur.

Pour ce faire, utilisez le set commande avec le -e option (erreur). Cela indique au script de se fermer chaque fois qu’une commande échoue ou renvoie un code de sortie supérieur à zéro. Aussi, en utilisant le -E L’option garantit que la détection et le piégeage des erreurs fonctionnent dans les fonctions du shell.

Pour intercepter également les variables non initialisées, ajoutez le -u (non défini). Pour vous assurer que les erreurs sont détectées dans les séquences canalisées, ajoutez le -o pipefail option. Sans cela, l’état de sortie d’une séquence de commandes canalisée est l’état de sortie du final commande dans la séquence. Une commande défaillante au milieu de la séquence canalisée ne serait pas détectée. La -o pipefail L’option doit figurer dans la liste des options.

La séquence à ajouter en haut de votre script est :

set -Eeuo pipefail

Voici un court script appelé « unset-var.sh », avec une variable non définie.

#!/bin/bash

set -Eeou pipefail

echo "$unset_variable"

echo "Do we see this line?"

Lorsque nous exécutons le script, la unset_variable est reconnue comme une variable non initialisée et le script est terminé.

./unset-var.sh

Utilisation de la commande set dans un script pour terminer le script si une erreur se produit

La deuxième echo la commande n’est jamais exécutée.

Utiliser le piège avec des erreurs

La commande Bash trap vous permet de désigner une commande ou une fonction qui doit être appelée lorsqu’un signal particulier est déclenché. Généralement, cela est utilisé pour capter des signaux tels que SIGINT qui est déclenché lorsque vous appuyez sur la combinaison de touches Ctrl + C. Ce script est « sigint.sh ».

#!/bin/bash

trap "echo -e 'nTerminated by Ctrl+c'; exit" SIGINT

counter=0

while true
do 
  echo "Loop number:" $((++counter))
  sleep 1
done

La trap la commande contient un echo commande et le exit commande. Il sera déclenché lorsque SIGINT est relevé. Le reste du script est une simple boucle. Si vous exécutez le script et appuyez sur Ctrl + C, vous verrez le message du trap définition, et le script se terminera.

./sigint.sh

Utiliser trap dans un script pour intercepter Ctrl+c

On peut utiliser trap avec le ERR signal pour détecter les erreurs au fur et à mesure qu’elles se produisent. Ceux-ci peuvent ensuite être transmis à une commande ou à une fonction. C’est « trap.sh ». Nous envoyons des notifications d’erreur à une fonction appelée error_handler.

#!/bin/bash

trap 'error_handler $? $LINENO' ERR

error_handler() 
  echo "Error: ($1) occurred on $2"


main() 
  echo "Inside main() function"
  bad_command
  second
  third
  exit $?


second() 
  echo "After call to main()"
  echo "Inside second() function"


third() 
  echo "Inside third() function"


main

La majeure partie du script se trouve à l’intérieur du main fonction, qui appelle la second et third les fonctions. Lorsqu’une erreur se produit, dans ce cas, parce que bad_command n’existe pas – le trap l’instruction dirige l’erreur vers error_handler fonction. Il transmet l’état de sortie de la commande ayant échoué et le numéro de ligne au error_handler fonction.

./trap.sh

Utiliser trap avec ERR pour intercepter les erreurs dans un script

Notre error_handler La fonction répertorie simplement les détails de l’erreur dans la fenêtre du terminal. Si vous le souhaitez, vous pouvez ajouter un exit commande à la fonction pour que le script se termine. Ou vous pouvez utiliser une série de if/elif/fi instructions pour effectuer différentes actions pour différentes erreurs.

Il peut être possible de corriger certaines erreurs, d’autres peuvent nécessiter l’arrêt du script.

Un dernier conseil

Détecter les erreurs signifie souvent anticiper les choses qui peuvent mal tourner et mettre en place du code pour gérer ces éventualités si elles se présentent. C’est en plus de s’assurer que le flux d’exécution et la logique interne de votre script sont corrects.

Si vous utilisez cette commande pour exécuter votre script, Bash vous montrera une sortie de trace lors de l’exécution du script :

bash -x your-script.sh

Bash écrit la sortie de trace dans la fenêtre du terminal. Il affiche chaque commande avec ses arguments, s’il y en a. Cela se produit après que les commandes ont été développées mais avant qu’elles ne soient exécutées.

Cela peut être une aide précieuse pour traquer les bogues insaisissables.

EN RELATION: Comment valider la syntaxe d’un script Linux Bash avant de l’exécuter

Source-135