Comment valider la syntaxe d’un script Linux Bash avant de l’exécuter
Les bogues et les fautes de frappe dans les scripts Linux Bash peuvent avoir des conséquences désastreuses lors de l’exécution du script. Voici quelques façons de vérifier la syntaxe de vos scripts avant même de les exécuter.
Sommaire
Ces insectes embêtants
Écrire du code est difficile. Ou pour être plus précis, écrire du code non trivial sans bogue est difficile. Et plus il y a de lignes de code dans un programme ou un script, plus il y a de chances qu’il y ait des bogues.
Le langage dans lequel vous programmez a une incidence directe sur cela. La programmation en assembleur est beaucoup plus difficile que la programmation en C, et la programmation en C est plus difficile que la programmation en Python. Plus le langage dans lequel vous programmez est de bas niveau, plus vous avez de travail à faire vous-même. Python peut profiter des routines intégrées de récupération de place, mais le C et l’assembly ne le font certainement pas.
L’écriture de scripts shell Linux pose ses propres défis. Avec un langage compilé comme C, un programme appelé compilateur lit votre code source (les instructions lisibles par l’homme que vous saisissez dans un fichier texte) et le transforme en un fichier exécutable binaire. Le fichier binaire contient les instructions du code machine que l’ordinateur peut comprendre et agir.
Le compilateur ne générera un fichier binaire que si le code source qu’il lit et analyse respecte la syntaxe et les autres règles du langage. Si vous épelez un mot reservé—un des mots de commande du langage—ou un nom de variable incorrect, le compilateur renverra une erreur.
Par exemple, certains langages insistent pour que vous déclariez une variable avant de l’utiliser, d’autres ne sont pas si pointilleux. Si le langage dans lequel vous travaillez vous oblige à déclarer des variables mais que vous oubliez de le faire, le compilateur lancera un message d’erreur différent. Aussi ennuyeuses que soient ces erreurs de compilation, elles détectent de nombreux problèmes et vous obligent à les résoudre. Mais même lorsque vous avez un programme qui n’a pas bogues syntaxiques cela ne veut pas dire qu’il n’y a pas de bugs. Loin de là.
Les bugs dus à défauts logiques sont généralement beaucoup plus difficiles à repérer. Si vous dites à votre programme d’ajouter deux et trois mais que vous vouliez vraiment qu’il ajoute deux et deux, vous n’obtiendrez pas la réponse que vous attendiez. Mais le programme fait ce pour quoi il a été écrit. Il n’y a rien de mal avec la composition ou la syntaxe du programme. Le problème, c’est vous. Vous avez écrit un programme bien formé qui ne fait pas ce que vous vouliez.
Les tests sont difficiles
Tester minutieusement un programme, même simple, prend du temps. L’exécuter plusieurs fois n’est pas suffisant ; vous devez vraiment tester tous les chemins d’exécution dans votre code, afin que toutes les parties du code soient vérifiées. Si le programme demande une entrée, vous devez fournir une plage suffisante de valeurs d’entrée pour tester toutes les conditions, y compris les entrées inacceptables.
Pour les langages de niveau supérieur, les tests unitaires et les tests automatisés permettent de faire des tests approfondis un exercice gérable. La question est donc de savoir s’il existe des outils que nous pouvons utiliser pour nous aider à écrire des scripts shell Bash sans bogue.
La réponse est oui, y compris le shell Bash lui-même.
Utilisation de Bash pour vérifier la syntaxe du script
La fête -n
(noexec) indique à Bash de lire un script et de vérifier les erreurs de syntaxe, sans exécuter le script. Selon ce que votre script est destiné à faire, cela peut être beaucoup plus sûr que de l’exécuter et de rechercher des problèmes.
Voici le script que nous allons vérifier. Ce n’est pas compliqué, c’est principalement un ensemble de if
déclarations. Il demande et accepte un nombre représentant un mois. Le script décide à quelle saison appartient le mois. Évidemment, cela ne fonctionnera pas si l’utilisateur ne fournit aucune entrée, ou s’il fournit une entrée invalide comme une lettre au lieu d’un chiffre.
#! /bin/bash read -p "Enter a month (1 to 12): " month # did they enter anything? if [ -z "$month" ] then echo "You must enter a number representing a month." exit 1 fi # is it a valid month? if (( "$month" < 1 || "$month" > 12)); then echo "The month must be a number between 1 and 12." exit 0 fi # is it a Spring month? if (( "$month" >= 3 && "$month" < 6)); then echo "That's a Spring month." exit 0 fi # is it a Summer month? if (( "$month" >= 6 && "$month" < 9)); then echo "That's a Summer month." exit 0 fi # is it an Autumn month? if (( "$month" >= 9 && "$month" < 12)); then echo "That's an Autumn month." exit 0 fi # it must be a Winter month echo "That's a Winter month." exit 0
Cette section vérifie si l’utilisateur a saisi quoi que ce soit. Il teste si le $month
la variable n’est pas définie.
if [ -z "$month" ] then echo "You must enter a number representing a month." exit 1 fi
Cette section vérifie s’ils ont saisi un nombre compris entre 1 et 12. Elle intercepte également une entrée non valide qui n’est pas un chiffre, car les lettres et les symboles de ponctuation ne se traduisent pas en valeurs numériques.
# is it a valid month? if (( "$month" < 1 || "$month" > 12)); then echo "The month must be a number between 1 and 12." exit 0 fi
Toutes les autres clauses If vérifient si la valeur dans $month
variable est entre deux valeurs. Si c’est le cas, le mois appartient à cette saison. Par exemple, si le mois saisi par l’utilisateur est 6, 7 ou 8, il s’agit d’un mois d’été.
# is it a Summer month? if (( "$month" >= 6 && "$month" < 9)); then echo "That's a Summer month." exit 0 fi
Si vous souhaitez travailler sur nos exemples, copiez et collez le texte du script dans un éditeur et enregistrez-le sous « seasons.sh ». Ensuite, rendez le script exécutable en utilisant le chmod
commander:
chmod +x seasons.sh
Nous pouvons tester le script en
- Ne fournissant aucune contribution.
- Fournir une entrée non numérique.
- Fournir une valeur numérique qui est en dehors de la plage de 1 à 12.
- Fournir des valeurs numériques comprises entre 1 et 12.
Dans tous les cas, on démarre le script avec la même commande. La seule différence est l’entrée que l’utilisateur fournit lorsqu’il est promu par le script.
./seasons.sh
Cela semble fonctionner comme prévu. Laissons Bash vérifier la syntaxe de notre script. Nous le faisons en invoquant le -n
(noexec) et en passant le nom de notre script.
bash -n ./seasons.sh
C’est un cas de « pas de nouvelles, bonnes nouvelles ». Nous renvoyer silencieusement à l’invite de commande est la manière de Bash de dire que tout semble OK. Sabotons notre script et introduisons une erreur.
Nous supprimerons le then
Depuis le premier if
clause.
# is it a valid month? if (( "$month" < 1 || "$month" > 12)); # "then" has been removed echo "The month must be a number between 1 and 12." exit 0 fi
Exécutons maintenant le script, d’abord sans puis avec l’entrée de l’utilisateur.
./seasons.sh
La première fois que le script est exécuté, l’utilisateur n’entre pas de valeur et le script se termine donc. La section que nous avons sabotée n’est jamais atteinte. Le script se termine sans message d’erreur de Bash.
La deuxième fois que le script est exécuté, l’utilisateur fournit une valeur d’entrée et la première clause if est exécutée pour vérifier l’intégrité de l’entrée de l’utilisateur. Cela déclenche le message d’erreur de Bash.
Notez que Bash vérifie la syntaxe de cette clause – et de toutes les autres lignes de code – car il ne se soucie pas de la logique du scénario. L’utilisateur n’est pas invité à entrer un nombre lorsque Bash vérifie le script, car le script n’est pas en cours d’exécution.
Les différents chemins d’exécution possibles du script n’affectent pas la façon dont Bash vérifie la syntaxe. Bash travaille simplement et méthodiquement du haut du script vers le bas, en vérifiant la syntaxe pour chaque ligne.
L’utilitaire ShellCheck
Un linter, du nom d’un outil de vérification de code source C de l’apogée d’Unix, est un outil d’analyse de code utilisé pour détecter les erreurs de programmation, les erreurs de style et l’utilisation suspecte ou douteuse du langage. Les linters sont disponibles pour de nombreux langages de programmation et sont réputés pour être pédants. Tout ce qu’un linter trouve n’est pas un bogue en soimais tout ce qu’ils font porter à votre attention mérite probablement l’attention.
ShellCheck est un outil d’analyse de code pour les scripts shell. Il se comporte comme un linter pour Bash.
Mettons nos disparus then
mot réservé dans notre script, et essayez autre chose. Nous supprimerons le crochet ouvrant « [« dutoutpremier[”fromtheveryfirstif
clause.
# did they enter anything? if -z "$month" ] # opening bracket "[" removed then echo "You must enter a number representing a month." exit 1 fi
si nous utilisons Bash pour vérifier le script, il ne trouve pas de problème.
bash -n seasons.sh
./seasons.sh
Mais quand nous essayons de Cours le script, nous voyons un message d’erreur. Et malgré le message d’erreur, le script continue de s’exécuter. C’est pourquoi certains bugs sont si dangereux. Si les actions entreprises plus loin dans le script reposent sur une entrée valide de l’utilisateur, le comportement du script sera imprévisible. Cela pourrait potentiellement mettre les données en danger.
La raison pour laquelle le Bash -n
(noexec) ne trouve pas l’erreur dans le script est le crochet ouvrant « [« estunprogrammeexterneappelé[”isanexternalprogramcalled[
. Cela ne fait pas partie de Bash. C’est une façon abrégée d’utiliser le test
commander.
Bash ne vérifie pas l’utilisation de programmes externes lorsqu’il valide un script.
Installation de ShellCheck
ShellCheck nécessite une installation. Pour l’installer sur Ubuntu, tapez :
sudo apt install shellcheck
Pour installer ShellCheck sur Fedora, utilisez cette commande. Notez que le nom du package est en casse mixte, mais lorsque vous exécutez la commande dans la fenêtre du terminal, tout est en minuscules.
sudo dnf install ShellCheck
Sur Manjaro et les distributions similaires basées sur Arch, nous utilisons pacman
:
sudo pacman -S shellcheck
Utilisation de ShellCheck
Essayons d’exécuter ShellCheck sur notre script.
shellcheck seasons.sh
ShellCheck trouve le problème et nous le signale, et fournit un ensemble de liens pour plus d’informations. Si vous faites un clic droit sur un lien et choisissez « Ouvrir le lien » dans le menu contextuel qui apparaît, le lien s’ouvrira dans votre navigateur.
ShellCheck trouve également un autre problème, qui n’est pas aussi grave. Il est signalé en texte vert. Cela indique qu’il s’agit d’un avertissement et non d’une erreur pure et simple.
Corrigeons notre erreur et remplaçons le « [« Unestratégiedecorrectiondeboguesconsisteàcorrigerd’abordlesproblèmeslesplusprioritairesetàréduireensuitelesproblèmesdemoindreprioritételsquelesavertissements[”Onebug-fixstrategyistocorrectthehighestpriorityissuesfirstandworkdowntothelowerpriorityissueslikewarningslater
Nous avons remplacé le «[ »manquantetavonsexécutéShellCheckunefoisdeplus[”andranShellCheckoncemore
shellcheck seasons.sh
La seule sortie de ShellCheck fait référence à notre avertissement précédent, donc c’est bien. Nous n’avons aucun problème prioritaire à résoudre.
L’avertissement nous indique que l’utilisation du read
commande sans le -r
(lire tel quel) entraînera le traitement de toutes les barres obliques inverses dans l’entrée comme des caractères d’échappement. Ceci est un bon exemple du type de sortie pédante qu’un linter peut générer. Dans notre cas, l’utilisateur ne devrait de toute façon pas entrer de barre oblique inverse – nous avons besoin qu’il entre un nombre.
Des avertissements comme celui-ci nécessitent un jugement de la part du programmeur. Faire l’effort de le réparer ou le laisser tel quel ? C’est une simple solution de deux secondes. Et cela empêchera l’avertissement d’encombrer la sortie de ShellCheck, alors autant suivre ses conseils. Nous ajouterons un « r » pour option les drapeaux sur le read
commande et enregistrez le script.
read -pr "Enter a month (1 to 12): " month
Exécuter ShellCheck une fois de plus nous donne un bon bilan de santé.
ShellCheck est votre ami
ShellCheck peut détecter, signaler et conseiller sur toute une gamme de problèmes. Découvrez leur galerie de mauvais codes, qui montre combien de types de problèmes il peut détecter.
C’est gratuit, rapide et facilite grandement l’écriture de scripts shell. Qu’est-ce qu’il ne faut pas aimer ?