Un script Bash est un fichier texte contenant des commandes shell. Avec un shebang en première ligne et les droits d’exécution, il devient un programme à part entière — capable de lire des arguments, de prendre des décisions, de répéter des tâches et de signaler son résultat. C’est la base de l’automatisation sous Linux.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Créer et exécuter un script avec shebang et
chmod +x - Utiliser des variables pour stocker et réutiliser des valeurs
- Écrire des conditions
if/then/fiavec[[ ]] - Répéter des actions avec
foretwhile - Organiser le code avec des fonctions
- Gérer les arguments
$1,$#,$@et les codes de retour$? - Déboguer avec
bash -xetshellcheck
Dans quel contexte ?
Section intitulée « Dans quel contexte ? »Un script Bash est utile dès que vous répétez la même séquence de commandes plus d’une ou deux fois :
- vérifier l’espace disque sur dix serveurs et envoyer une alerte si un seuil est dépassé
- créer un utilisateur avec son répertoire home, ses clés SSH et ses permissions en une commande
- générer un rapport quotidien à partir des logs nginx et l’envoyer par e-mail
- valider l’état d’un service avant de lancer un déploiement
- convertir ou renommer un lot de fichiers selon un pattern
En préparation RHCSA, les scripts shell sont au programme de façon explicite : vous devez être capable d’en écrire un à partir de zéro sous contrainte de temps.
Créer et exécuter son premier script
Section intitulée « Créer et exécuter son premier script »La première ligne d’un script indique quel interpréteur l’exécutera. Sans elle, le shell par défaut du système est utilisé — et ce n’est pas forcément Bash.
#!/bin/bash
echo "Bonjour, $USER !"Enregistrez ce fichier sous bonjour.sh, puis rendez-le exécutable :
chmod +x bonjour.sh./bonjour.shBonjour, bob !#!/bin/bash: le shebang — le système lit ce chemin et lance cet interpréteurchmod +x: ajoute le droit d’exécution au propriétaire./: exécute le script depuis le répertoire courant
Variables
Section intitulée « Variables »Une variable se déclare sans espace autour du = et s’utilise avec $ ou ${}.
#!/bin/bash
nom="alice"nombre=42
echo "Utilisateur : $nom"echo "Valeur : ${nombre}"Utilisateur : aliceValeur : 42Substitution de commande
Section intitulée « Substitution de commande »Pour stocker le résultat d’une commande dans une variable, utilisez $() :
date_du_jour=$(date '+%Y-%m-%d')nb_utilisateurs=$(wc -l < /etc/passwd)
echo "Date : $date_du_jour"echo "Comptes : $nb_utilisateurs"Date : 2026-04-10Comptes : 42Lire une entrée utilisateur
Section intitulée « Lire une entrée utilisateur »echo "Entrez votre nom :"read -r prenomecho "Bonjour, $prenom !"-r désactive l’interprétation des backslashes — toujours utiliser read -r.
Variables automatiques utiles
Section intitulée « Variables automatiques utiles »| Variable | Contenu |
|---|---|
$USER | Nom de l’utilisateur courant |
$HOME | Répertoire personnel |
$PWD | Répertoire courant |
$RANDOM | Nombre aléatoire entre 0 et 32767 |
Conditions
Section intitulée « Conditions »La structure if/then/fi exécute un bloc si une condition est vraie. Utilisez [[ ]] (double crochets) — plus sûr et plus lisible que [ ].
#!/bin/bash
fichier="$1"
if [[ -f "$fichier" ]]; then echo "Le fichier existe."else echo "Le fichier est introuvable."fiTests sur les fichiers
Section intitulée « Tests sur les fichiers »| Opérateur | Condition vraie si… |
|---|---|
-f "$f" | $f est un fichier ordinaire |
-d "$f" | $f est un répertoire |
-e "$f" | $f existe (fichier ou répertoire) |
-r "$f" | $f est lisible |
-w "$f" | $f est modifiable |
-x "$f" | $f est exécutable |
Tests sur les chaînes
Section intitulée « Tests sur les chaînes »| Opérateur | Condition vraie si… |
|---|---|
-z "$s" | $s est vide |
-n "$s" | $s n’est pas vide |
"$a" == "$b" | les deux chaînes sont égales |
"$a" != "$b" | les deux chaînes sont différentes |
Tests numériques
Section intitulée « Tests numériques »| Opérateur | Signification |
|---|---|
-eq | égal |
-ne | différent |
-lt | inférieur strict |
-le | inférieur ou égal |
-gt | supérieur strict |
-ge | supérieur ou égal |
score=85
if [[ $score -ge 90 ]]; then echo "Excellent"elif [[ $score -ge 70 ]]; then echo "Bien"else echo "À améliorer"fiBienfor — itérer sur une liste
Section intitulée « for — itérer sur une liste »for service in nginx ssh cron; do echo "Service : $service"doneService : nginxService : sshService : cronSur les fichiers d’un dossier :
for fichier in /etc/*.conf; do echo "Config : $fichier"doneSur une plage numérique :
for i in {1..5}; do echo "Itération $i"donewhile — boucle conditionnelle
Section intitulée « while — boucle conditionnelle »compteur=1
while [[ $compteur -le 3 ]]; do compteur=$((compteur + 1)) echo "Tour $compteur"doneTour 2Tour 3Tour 4Lire un fichier ligne par ligne
Section intitulée « Lire un fichier ligne par ligne »Pattern courant en administration système :
while IFS= read -r ligne; do echo "→ $ligne"done < /etc/hostnameIFS=: désactive le découpage par espaces/tabulations-r: préserve les backslashes
Fonctions
Section intitulée « Fonctions »Une fonction regroupe des instructions réutilisables. Elle se déclare avant d’être appelée.
#!/bin/bash
afficher_entete() { local titre="$1" echo "" echo "=== $titre ==="}
afficher_entete "Rapport système"afficher_entete "Fin"=== Rapport système ===
=== Fin ===local: la variable reste locale à la fonction — indispensable pour éviter les effets de bord$1,$2… : arguments passés à la fonction (indépendants des arguments du script)
Retourner une valeur textuelle
Section intitulée « Retourner une valeur textuelle »Une fonction retourne un code de sortie (0–255), pas une chaîne. Pour retourner du texte, utilisez echo et récupérez avec $() :
nom_complet() { local prenom="$1" local nom="$2" echo "${prenom} ${nom}"}
resultat=$(nom_complet "alice" "martin")echo "Bonjour, $resultat !"Bonjour, alice martin !Arguments du script
Section intitulée « Arguments du script »Quand vous passez des arguments à votre script, ils sont accessibles via des variables spéciales :
| Variable | Contenu |
|---|---|
$0 | Nom du script |
$1, $2… | Premier, deuxième argument |
$# | Nombre total d’arguments |
$@ | Tous les arguments (liste) |
#!/bin/bash
if [[ $# -ne 2 ]]; then echo "Usage: $0 <source> <destination>" >&2 exit 1fi
echo "Script : $0"echo "Source : $1"echo "Dest : $2"echo "Nb args : $#"./copier.sh /etc/hosts /tmp/hosts.bakScript : ./copier.shSource : /etc/hostsDest : /tmp/hosts.bakNb args : 2Codes de sortie
Section intitulée « Codes de sortie »Chaque commande se termine avec un code de sortie : 0 = succès, valeur non nulle = erreur. $? contient le code de la dernière commande exécutée.
ls /etc/passwdecho "Code : $?" # 0 — succès
ls /fichier-inexistant 2>/dev/nullecho "Code : $?" # 2 — erreurDans un script, exit définit le code retourné à l’appelant :
if [[ ! -d "$1" ]]; then echo "Erreur : '$1' n'est pas un répertoire." >&2 exit 1fi
# … traitement …exit 0Exemple complet
Section intitulée « Exemple complet »Ce script illustre tous les concepts : fonctions, argument, condition, boucle for et codes de sortie.
#!/bin/bash# generer-rapport.sh — rapport d'un répertoire# Usage: ./generer-rapport.sh <repertoire>
set -euo pipefail
afficher_entete() { local titre="$1" echo "" echo "=== $titre ==="}
if [[ $# -ne 1 ]]; then echo "Usage: $0 <repertoire>" >&2 exit 1fi
repertoire="$1"
if [[ ! -d "$repertoire" ]]; then echo "Erreur : '$repertoire' n'est pas un répertoire." >&2 exit 1fi
afficher_entete "Rapport — $repertoire"echo "Date : $(date '+%Y-%m-%d %H:%M')"echo "Utilisateur: $USER"echo ""
nb_fichiers=0for entree in "$repertoire"/*; do [[ -f "$entree" ]] && nb_fichiers=$((nb_fichiers + 1))done
echo "Fichiers : $nb_fichiers"exit 0./generer-rapport.sh /etc=== Rapport — /etc ===Date : 2026-04-10 07:44Utilisateur: bob
Fichiers : 158Déboguer un script
Section intitulée « Déboguer un script »bash -x — voir chaque commande avant exécution
Section intitulée « bash -x — voir chaque commande avant exécution »bash -x ./generer-rapport.sh /etcChaque ligne exécutée est préfixée de + avec les variables substituées. C’est le moyen le plus rapide de suivre l’exécution pas à pas.
set -x / set +x dans le script
Section intitulée « set -x / set +x dans le script »Pour n’activer le debug que sur une portion du code :
set -x # début du debugmv "$src" "$dst"set +x # fin du debugshellcheck — analyse statique
Section intitulée « shellcheck — analyse statique »shellcheck détecte les erreurs de syntaxe et les mauvaises pratiques avant d’exécuter le script.
# Debian/Ubuntusudo apt install shellcheck
# RHEL/Fedorasudo dnf install shellcheckshellcheck mon-script.shmon-script.sh:12:8: warning: Double quote to prevent globbing and word splitting. [SC2086]Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Correction |
|---|---|---|
Permission denied à l’exécution | Droit +x absent | chmod +x mon-script.sh |
bad interpreter: No such file or directory | Shebang incorrect ou encodage Windows (CRLF) | Vérifier #!/bin/bash ; convertir avec dos2unix mon-script.sh |
unbound variable | Variable non définie utilisée avec set -u | Initialiser la variable ou utiliser ${VAR:-} |
| Rien ne se passe après lancement | Shebang manquant ou script lancé avec sh | Ajouter #!/bin/bash et lancer avec ./script.sh |
syntax error near unexpected token | fi/done/guillemet manquant | Lancer shellcheck script.sh pour localiser |
À retenir
Section intitulée « À retenir »- Un script commence toujours par
#!/bin/bashet se rend exécutable avecchmod +x. - Les variables se déclarent sans espace autour du
=et s’utilisent entre guillemets :"$var". - Utilisez
[[ ]]pour les tests — plus sûr que[ ]. - Les fonctions déclarent leurs variables internes avec
local. $1,$2,$#,$@donnent accès aux arguments passés au script.exit 0= succès,exit 1= erreur — toujours explicite.bash -xpour déboguer,shellcheckpour détecter les erreurs à l’avance.