Comment vérifier la syntaxe d'un script Bash sans l'exécuter?


267

Est-il possible de vérifier une syntaxe de script bash sans l'exécuter?

En utilisant Perl, je peux courir perl -c 'script name'. Existe-t-il une commande équivalente pour les scripts bash?


1
En relation: Existe
blong

Réponses:


381
bash -n scriptname

Peut-être une mise en garde évidente: cela valide la syntaxe mais ne vérifie pas si votre script bash essaie d'exécuter une commande qui n'est pas sur votre chemin, comme à la ech helloplace de echo hello.


9
Dans la page de manuel de bash, sous "SHELL BUILTIN COMMANDS / set", -n est documenté, et comme l'indique le début de la page de manuel, bash interprète toutes les options à caractère unique qui le setfont.
ephémient

24
pour ajouter à la mise en garde non évidente (pour moi), il ne détectera pas non plus une erreur causée par un espace manquant if ["$var" == "string" ]au lieu deif [ "$var" == "string" ]
Brynjar

11
@Brynjar C'est parce que c'est juste une vérification de la syntaxe. Le crochet ouvert n'est pas une syntaxe, c'est le nom de la fonction à exécuter. type [dit "[est un shell intégré". Il délègue finalement au testprogramme, mais il s'attend également à une clôture. Donc c'est comme if test"$var", ce qui n'est pas ce que l'auteur voulait dire, mais qui est syntaxiquement valide (disons que $ var a une valeur de "a", alors nous verrons "bash: testa: commande introuvable"). Le point est que syntaxiquement, il n'y a pas d'espace manquant.
Joshua Cheek

2
@JoshuaCheek: la fonction intégrée [n'est invoquée dans ce cas que si elle $varse développe sur une chaîne vide . Si se $vardéveloppe en une chaîne non vide , [est concaténé avec cette chaîne et est interprété comme un nom de commande (pas un nom de fonction ) par Bash, et, oui, c'est syntaxiquement valide, mais, comme vous le dites, évidemment pas l'intention. Si vous utilisez à la [[place de [, même s'il [[s'agit d'un mot clé shell (plutôt que d'un mot clé intégré), vous obtiendrez le même résultat, car la concaténation de chaîne involontaire remplace toujours la reconnaissance du mot clé.
mklement0

2
@JoshuaCheek: Bash est toujours une vérification de syntaxe ici: il vérifie la syntaxe d' invocation de commande simple : ["$var"est syntaxiquement une expression de nom de commande valide ; de même, les jetons ==et "$string"sont des arguments de commande valides . ( En général, builtin [est analysé avec commande syntaxe, tandis que [[- comme une coquille mot - clé - est analysé différemment.) La commande interne shell [ne pas déléguer au « testprogramme » (utilitaire externe): bash, dash, ksh, zshtous ont intégré les versions des deux [ettestet ils n'appellent pas leurs homologues externes.
mklement0

127

Le temps change tout. Voici un site Web qui fournit une vérification de la syntaxe en ligne pour le script shell.

J'ai trouvé qu'il est très puissant pour détecter les erreurs courantes.

entrez la description de l'image ici

À propos de ShellCheck

ShellCheck est un outil d'analyse statique et de peluchage pour les scripts sh / bash. Il est principalement axé sur la gestion des erreurs de syntaxe et des pièges de niveau débutant et intermédiaire typiques lorsque le shell donne simplement un message d'erreur cryptique ou un comportement étrange, mais il signale également quelques problèmes plus avancés où les cas d'angle peuvent provoquer des échecs retardés.

Le code source de Haskell est disponible sur GitHub!


5
Excellent conseil; sur OSX vous pouvez également installer le CLI shellcheck.net, shellcheckvia Homebrew : brew install shellcheck.
mklement0

3
Aussi sur Debian et ses amis:apt-get install shellcheck
cet autre gars

Pour Ubuntu trusty, ce paquet doit être installé depuis trusty-backports.
Peterino

Comme mentionné ci-dessus, une dépendance fiable est nécessaire et peut l'installer comme ci-dessous dans Ubuntu 14.04: sudo apt-get -f install, puis: sudo sudo apt-get install shellcheck
zhihong

C'est vraiment utile, mais il n'utilise pas l'analyseur de Bash mais le sien. Dans la plupart des cas, c'est assez bon et cela peut identifier à la fois l'analyse et d'autres problèmes, mais il y a au moins un cas de bord (et probablement d'autres que je n'ai pas vu) où il n'analyse pas tout à fait de la même manière.
Daniel H

38

J'active également l'option 'u' sur chaque script bash que j'écris afin de faire des vérifications supplémentaires:

set -u 

Cela signalera l'utilisation de variables non initialisées, comme dans le script suivant 'check_init.sh'

#!/bin/sh
set -u
message=hello
echo $mesage

Exécution du script:

$ check_init.sh

Rapportera les éléments suivants:

./check_init.sh[4]: mesage: paramètre non défini.

Très utile pour attraper les fautes de frappe


4
je mets toujours ces drapeaux dans mes scripts bash, si ça passe, c'est bon d'aller "set -o errexit" "set -o nounset" "set -o pipefail"
μολὼν.λαβέ

+1 pour set -ubien que cela ne réponde pas vraiment à la question, car vous devez exécuter le script pour obtenir le message d'erreur. Ne bash -n check_init.shmontre même pas cet avertissement
rubo77

23
sh  -n   script-name 

Lance ça. S'il y a des erreurs de syntaxe dans le script, il renvoie le même message d'erreur. S'il n'y a pas d'erreur, il sort sans donner de message. Vous pouvez vérifier immédiatement en utilisant echo $?, qui retournera 0confirmant le succès sans aucune erreur.

Cela a bien fonctionné pour moi. J'ai couru sous Linux OS, Bash Shell.


1
Bien qu'il ne soit pas exactement lié à la vérification de la syntaxe bash - utiliser set -x et set + x pour déboguer le script complet ou des sections du script est très utile
GuruM

Merci pour cela je ne savais pas ne connaissais pas le -n mais ce que je voulais c'était @GuruM> sh -x test.sh car cela affiche la sortie générée du script
zzapper

1
Oui. J'ai oublié de mentionner que vous pouvez faire ce qui suit sur la ligne de commande: 1) bash -x test.sh #this exécute l'ensemble du script en «mode débogage» 2) set + x; bash test.sh; set -x #set debug mode on / off before / after script run Dans le script: a) #! / bin / bash -x #add 'debug mode' en haut du script b) set + x; code; set -x #add 'debug mode' pour n'importe quelle section du script
GuruM

sh -nne vérifiera probablement pas que le script est un script Bash valide. Cela pourrait donner de faux négatifs. shest une variante du shell Bourne qui n'est généralement pas Bash. Par exemple dans Ubuntu Linux realpath -e $(command -v sh)donne / bin / dash
jarno

4

Je vérifie en fait tous les scripts bash dans le répertoire actuel pour les erreurs de syntaxe SANS les exécuter à l'aide de l' findoutil:

Exemple:

find . -name '*.sh' -exec bash -n {} \;

Si vous souhaitez l'utiliser pour un seul fichier, modifiez simplement le caractère générique avec le nom du fichier.


3

commande null [deux points] également utile lors du débogage pour voir la valeur de la variable

set -x
for i in {1..10}; do
    let i=i+1
    : i=$i
done
set - 

il utilise des extensions de paramètres
mug896

cela fonctionne, car set -xaffiche chaque ligne avant son exécution
rubo77


1

Si vous avez besoin dans une variable de la validité de tous les fichiers d'un répertoire (git pre-commit hook, build lint script), vous pouvez attraper la sortie stderr des commandes "sh -n" ou "bash -n" (voir autres réponses) dans une variable, et avoir un "si / autre" basé sur cette

bashErrLines=$(find bin/ -type f -name '*.sh' -exec sh -n {} \;  2>&1 > /dev/null)
  if [ "$bashErrLines" != "" ]; then 
   # at least one sh file in the bin dir has a syntax error
   echo $bashErrLines; 
   exit; 
  fi

Changez "sh" par "bash" selon vos besoins

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.