Comment utiliser la commande find sous Linux
Agence web » Actualités du digital » Comment valider la syntaxe d’un script Linux Bash avant de l’exécuter

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.

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

Définition de l'autorisation exécutable sur un script

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

Tester un script avec une variété d'entrées valides et non valides

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

Utiliser Bash pour tester la syntaxe d'un script

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

Tester un script avec des entrées invalides et valides

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

Un message d'erreur d'un script qui a réussi la vérification de la syntaxe sans aucun problème détecté

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

Installer shellcheck sur Ubuntu

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

Installer shellcheck sur Fedora

Sur Manjaro et les distributions similaires basées sur Arch, nous utilisons pacman:

sudo pacman -S shellcheck

Installer shellcheck sur Manjaro

Utilisation de ShellCheck

Essayons d’exécuter ShellCheck sur notre script.

shellcheck seasons.sh

Vérification d'un script avec ShellCheck

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 rapporte les erreurs et les avertissements

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

Vérifier un script une deuxième fois avec ShellCheck

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é.

Aucune erreur ou avertissement signalé par ShellCheck

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 ?

★★★★★