Aller au contenu
Administration Linux medium

Écrire un script shell

14 min de lecture

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.

  • 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/fi avec [[ ]]
  • Répéter des actions avec for et while
  • Organiser le code avec des fonctions
  • Gérer les arguments $1, $#, $@ et les codes de retour $?
  • Déboguer avec bash -x et shellcheck

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.


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 :

Fenêtre de terminal
chmod +x bonjour.sh
./bonjour.sh
Sortie
Bonjour, bob !
  • #!/bin/bash : le shebang — le système lit ce chemin et lance cet interpréteur
  • chmod +x : ajoute le droit d’exécution au propriétaire
  • ./ : exécute le script depuis le répertoire courant

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}"
Sortie
Utilisateur : alice
Valeur : 42

Pour stocker le résultat d’une commande dans une variable, utilisez $() :

Fenêtre de terminal
date_du_jour=$(date '+%Y-%m-%d')
nb_utilisateurs=$(wc -l < /etc/passwd)
echo "Date : $date_du_jour"
echo "Comptes : $nb_utilisateurs"
Sortie
Date : 2026-04-10
Comptes : 42
Fenêtre de terminal
echo "Entrez votre nom :"
read -r prenom
echo "Bonjour, $prenom !"

-r désactive l’interprétation des backslashes — toujours utiliser read -r.

VariableContenu
$USERNom de l’utilisateur courant
$HOMERépertoire personnel
$PWDRépertoire courant
$RANDOMNombre aléatoire entre 0 et 32767

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."
fi
OpérateurCondition 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
OpérateurCondition 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
OpérateurSignification
-eqégal
-nedifférent
-ltinférieur strict
-leinférieur ou égal
-gtsupérieur strict
-gesupérieur ou égal
Fenêtre de terminal
score=85
if [[ $score -ge 90 ]]; then
echo "Excellent"
elif [[ $score -ge 70 ]]; then
echo "Bien"
else
echo "À améliorer"
fi
Sortie
Bien

Fenêtre de terminal
for service in nginx ssh cron; do
echo "Service : $service"
done
Sortie
Service : nginx
Service : ssh
Service : cron

Sur les fichiers d’un dossier :

Fenêtre de terminal
for fichier in /etc/*.conf; do
echo "Config : $fichier"
done

Sur une plage numérique :

Fenêtre de terminal
for i in {1..5}; do
echo "Itération $i"
done
Fenêtre de terminal
compteur=1
while [[ $compteur -le 3 ]]; do
compteur=$((compteur + 1))
echo "Tour $compteur"
done
Sortie
Tour 2
Tour 3
Tour 4

Pattern courant en administration système :

Fenêtre de terminal
while IFS= read -r ligne; do
echo "$ligne"
done < /etc/hostname
  • IFS= : désactive le découpage par espaces/tabulations
  • -r : préserve les backslashes

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"
Sortie
=== 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)

Une fonction retourne un code de sortie (0–255), pas une chaîne. Pour retourner du texte, utilisez echo et récupérez avec $() :

Fenêtre de terminal
nom_complet() {
local prenom="$1"
local nom="$2"
echo "${prenom} ${nom}"
}
resultat=$(nom_complet "alice" "martin")
echo "Bonjour, $resultat !"
Sortie
Bonjour, alice martin !

Quand vous passez des arguments à votre script, ils sont accessibles via des variables spéciales :

VariableContenu
$0Nom du script
$1, $2Premier, deuxième argument
$#Nombre total d’arguments
$@Tous les arguments (liste)
#!/bin/bash
if [[ $# -ne 2 ]]; then
echo "Usage: $0 <source> <destination>" >&2
exit 1
fi
echo "Script : $0"
echo "Source : $1"
echo "Dest : $2"
echo "Nb args : $#"
Fenêtre de terminal
./copier.sh /etc/hosts /tmp/hosts.bak
Sortie
Script : ./copier.sh
Source : /etc/hosts
Dest : /tmp/hosts.bak
Nb args : 2

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.

Fenêtre de terminal
ls /etc/passwd
echo "Code : $?" # 0 — succès
ls /fichier-inexistant 2>/dev/null
echo "Code : $?" # 2 — erreur

Dans un script, exit définit le code retourné à l’appelant :

Fenêtre de terminal
if [[ ! -d "$1" ]]; then
echo "Erreur : '$1' n'est pas un répertoire." >&2
exit 1
fi
# … traitement …
exit 0

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 1
fi
repertoire="$1"
if [[ ! -d "$repertoire" ]]; then
echo "Erreur : '$repertoire' n'est pas un répertoire." >&2
exit 1
fi
afficher_entete "Rapport — $repertoire"
echo "Date : $(date '+%Y-%m-%d %H:%M')"
echo "Utilisateur: $USER"
echo ""
nb_fichiers=0
for entree in "$repertoire"/*; do
[[ -f "$entree" ]] && nb_fichiers=$((nb_fichiers + 1))
done
echo "Fichiers : $nb_fichiers"
exit 0
Fenêtre de terminal
./generer-rapport.sh /etc
Sortie
=== Rapport — /etc ===
Date : 2026-04-10 07:44
Utilisateur: bob
Fichiers : 158

Fenêtre de terminal
bash -x ./generer-rapport.sh /etc

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

Pour n’activer le debug que sur une portion du code :

Fenêtre de terminal
set -x # début du debug
mv "$src" "$dst"
set +x # fin du debug

shellcheck détecte les erreurs de syntaxe et les mauvaises pratiques avant d’exécuter le script.

Fenêtre de terminal
# Debian/Ubuntu
sudo apt install shellcheck
# RHEL/Fedora
sudo dnf install shellcheck
Fenêtre de terminal
shellcheck mon-script.sh
Exemple de sortie
mon-script.sh:12:8: warning: Double quote to prevent globbing and word splitting. [SC2086]

SymptômeCause probableCorrection
Permission denied à l’exécutionDroit +x absentchmod +x mon-script.sh
bad interpreter: No such file or directoryShebang incorrect ou encodage Windows (CRLF)Vérifier #!/bin/bash ; convertir avec dos2unix mon-script.sh
unbound variableVariable non définie utilisée avec set -uInitialiser la variable ou utiliser ${VAR:-}
Rien ne se passe après lancementShebang manquant ou script lancé avec shAjouter #!/bin/bash et lancer avec ./script.sh
syntax error near unexpected tokenfi/done/guillemet manquantLancer shellcheck script.sh pour localiser

  • Un script commence toujours par #!/bin/bash et se rend exécutable avec chmod +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 -x pour déboguer, shellcheck pour détecter les erreurs à l’avance.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn