Résoudre les erreurs de syntaxe Bash courantes : un guide pratique
Corrigez les erreurs de syntaxe Bash courantes avec des exemples pour les guillemets, les crochets, les variables, les redirections et les problèmes de recherche de commandes.
Résoudre les erreurs de syntaxe Bash courantes : un guide pratique
Les erreurs de syntaxe Bash proviennent généralement de petites erreurs : un guillemet manquant, un mauvais crochet, une redirection mal placée ou une variable qui s'est développée en quelque chose d'inattendu. Lorsque votre script Bash s'arrête avec syntax error near unexpected token, commencez par vérifier la ligne précédant celle signalée par Bash, puis exécutez le script via une vérification syntaxique.
Utilisez cette vérification rapide avant d'exécuter un script modifié sur un serveur :
bash -n script.sh
bash -n analyse le fichier sans exécuter les commandes. Cela ne détectera pas tous les bugs logiques, mais cela détecte de nombreux guillemets cassés, des instructions fi manquantes et des boucles mal formées.
Guillemets manquants
Les guillemets non fermés sont l'un des moyens les plus rapides de confondre l'analyseur.
name="deploy
printf 'Déploiement de %s\n' "$name"
Bash continue de lire les lignes suivantes car il cherche toujours le " de fermeture. Corrigez-le en fermant le guillemet et en citant les expansions de variables qui peuvent contenir des espaces :
name="deploy"
printf 'Déploiement de %s\n' "$name"
Utilisez des guillemets doubles lorsque vous voulez que les variables se développent. Utilisez des guillemets simples lorsque vous voulez du texte littéral :
printf 'HOME reste littéral : $HOME\n'
printf "HOME se développe : %s\n" "$HOME"
Mauvais blocs if, for et while
Chaque commande composée a besoin de son mot-clé de fermeture. En manquer un signale souvent l'erreur près de la fin du fichier.
if systemctl is-active --quiet nginx; then
echo "nginx est en cours d'exécution"
# fi manquant
Version corrigée :
if systemctl is-active --quiet nginx; then
echo "nginx est en cours d'exécution"
fi
Le même modèle s'applique aux boucles et aux instructions case :
for host in web1 web2 web3; do
ssh "$host" uptime
done
case "$env" in
prod) echo "production" ;;
dev) echo "développement" ;;
*) echo "inconnu" ;;
esac
Erreurs de crochets et de tests
La commande [ est une vraie commande, donc elle a besoin d'espaces autour de ses arguments et avant le crochet de fermeture.
Cassé :
if [$count -gt 5]; then
echo "trop nombreux"
fi
Corrigé :
if [ "$count" -gt 5 ]; then
echo "trop nombreux"
fi
Pour les scripts spécifiques à Bash, [[ ... ]] est souvent plus sûr pour les tests de chaînes car il gère les variables vides plus gracieusement et prend en charge la correspondance de motifs :
if [[ "$file" == *.log ]]; then
gzip "$file"
fi
Utilisez des opérateurs numériques pour les nombres et des opérateurs de chaînes pour le texte :
[[ "$status" == "prêt" ]] # comparaison de chaînes
[[ "$retries" -lt 3 ]] # comparaison numérique
Problèmes d'expansion de variables
Une erreur courante est d'ajouter des espaces autour de = lors de l'affectation. Bash traite cela comme une commande au lieu d'une affectation de variable.
Cassé :
backup_dir = /var/backups
Corrigé :
backup_dir=/var/backups
Utilisez des accolades lorsque le nom de la variable touche d'autres textes :
service="nginx"
log="/var/log/${service}.log"
Sans accolades, Bash peut lire un nom de variable plus long que prévu.
Erreurs command not found
command not found n'est pas toujours une erreur de syntaxe. Cela signifie généralement que Bash n'a pas pu trouver un exécutable avec ce nom.
Vérifiez d'abord les fautes de frappe :
systemctl status nginx
Ensuite, vérifiez si la commande existe et est dans PATH :
command -v systemctl
printf '%s\n' "$PATH"
Si le script s'exécute sous cron, systemd ou un travail CI, PATH peut être plus court que votre shell interactif. Utilisez des chemins absolus pour les commandes critiques ou définissez PATH près du début du script :
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
export PATH
Erreurs de redirection et de pipe
L'ordre de redirection compte. Cette commande écrit stdout dans app.log puis envoie stderr au même endroit :
./deploy.sh >app.log 2>&1
Celle-ci est différente car stderr est copié vers l'ancien stdout avant que stdout ne soit redirigé :
./deploy.sh 2>&1 >app.log
Pour les pipelines, rappelez-vous que Bash renvoie normalement le code de sortie de la dernière commande. Utilisez pipefail lorsqu'une commande échouée au milieu doit faire échouer tout le pipeline :
set -o pipefail
kubectl get pods | grep CrashLoopBackOff
Un flux de débogage pratique
Commencez par une vérification syntaxique :
bash -n script.sh
Exécutez avec traçage lorsque la syntaxe est valide mais que le comportement est incorrect :
bash -x script.sh
Pour des scripts de production plus sûrs, ajoutez le mode strict délibérément et testez le script après chaque modification :
set -euo pipefail
set -e se termine sur de nombreux échecs de commande, set -u traite les variables non définies comme des erreurs, et pipefail détecte les échecs à l'intérieur des pipelines. Ces options sont utiles, mais elles peuvent changer le comportement du script, donc activez-les intentionnellement au lieu de les insérer dans un ancien script sans test.
À retenir
La plupart des erreurs de syntaxe Bash deviennent simples une fois que vous vérifiez les guillemets, les mots-clés de fermeture, l'espacement des crochets, les affectations de variables et les redirections dans cet ordre. Gardez bash -n et bash -x dans votre flux de travail normal, et testez les scripts avec le même shell et le même environnement qui les exécutera en production.