Dans cette leçon, tu vas apprendre à rendre tes scripts Bash robustes : intercepter les signaux (Ctrl+C), gérer les erreurs, quitter proprement et nettoyer les fichiers temporaires. Quand un script est interrompu ou échoue, c'est souvent parce qu'il n'a pas été conçu pour gérer ces situations.
Un **signal** est un message envoyé par le système ou par un utilisateur à un processus en cours d'exécution. C'est une forme de communication entre processus — et entre toi et tes scripts.
| Signal | Numéro | Signification | Action par défaut |
|---|---|---|---|
SIGINT (Ctrl+C) | 2 | Interruption par l'utilisateur | Termine le processus |
SIGTERM | 15 | Demande d'arrêt propre | Termine le processus |
SIGKILL | 9 | Arrêt forcé | Termine immédiatement (impossible à intercepter) |
SIGHUP | 1 | Le terminal a été fermé | Le processus se termine ou se reconfigure |
SIGEXIT | 0 | Sortie normale du script | — |
Quand tu tapes Ctrl+C dans un terminal, tu envoies un SIGINT au processus en avant-plan. Par défaut, cela termine le programme. Mais avec trap, tu peux décider ce qui se passe à la place.
trap — intercepter les signauxtrap te permet d'exécuter une commande (ou une fonction) quand un signal précis est reçu. C'est indispensable pour nettoyer proprement.
trap 'commande' SIGNAL
trap 'fonction' SIGNAL1 SIGNAL2
#!/bin/bash
# Fonction de nettoyage
nettoyer() {
echo "Nettoyage en cours..."
rm -f /tmp/mon-script.lock
rm -f /tmp/mon-script.tmp
echo "Programme terminé proprement."
}
# Intercepter Ctrl+C (SIGINT) et sortie normale (EXIT)
trap nettoyer EXIT INT TERM
echo "Mon script tourne... (Ctrl+C pour arrêter)"
sleep 30
**Ce qui se passe :**
nettoyerCtrl+C → SIGINT → nettoyer s'exécute → le lockfile est suppriméEXIT → nettoyer s'exécute aussi**💡 Bonnes pratiques :** Utilise toujours
trappour supprimer les fichiers temporaires et libérer les ressources (locks, sockets, connexions).
set -e et set -uset -ePar défaut, Bash continue l'exécution même si une commande échoue. set -e change ce comportement.
#!/bin/bash
set -e # Quitte immédiatement si une commande échoue
echo "Création du dossier..."
mkdir /tmp/mon-projet
cd /tmp/mon-projet
echo "Projet créé."
Si mkdir échoue (droits insuffisants, disque plein), le script s'arrête là.
set -u#!/bin/bash
set -u
echo "Salutation pour $NOM" # Si $NOM n'existe pas → erreur
Sans set -u, Bash remplace $NOM par une chaîne vide sans protester. Avec set -u, le script s'arrête.
#!/bin/bash
set -euo pipefail
| Option | Rôle |
|---|---|
-e | Quitte sur erreur |
-u | Quitte sur variable non définie |
-o pipefail | Quitte si une commande dans un pipe échoue (pas seulement la dernière) |
Chaque commande retourne un **code de sortie** : 0 = succès, != 0 = erreur.
# Lancer une commande et tester son résultat
mkdir /backup || { echo "Échec de la création du dossier"; exit 1; }
# Ou avec if
if grep -q "error" /var/log/syslog; then
echo "Des erreurs ont été trouvées !"
fi
# Capturer le code de sortie dans une variable
ls /etc/passwd
resultat=$?
echo "Code de sortie de ls : $resultat" # 0 si succès
#!/bin/bash
#
# sauvegarde-robuste.sh — Exemple de script avec gestion de signaux et d'erreurs
#
set -euo pipefail
# Répertoires
SOURCE="/home/david/documents"
DEST="/tmp/backup-$(date +%Y%m%d).tar.gz"
LOCKFILE="/tmp/sauvegarde.lock"
# Fonction de nettoyage
cleanup() {
local exit_code=$?
rm -f "$LOCKFILE"
if [ $exit_code -ne 0 ]; then
echo "Sauvegarde échouée (code: $exit_code)" >&2
fi
exit $exit_code
}
# Intercepter les signaux
trap cleanup EXIT INT TERM
# Vérifier qu'une seule instance tourne
if [ -f "$LOCKFILE" ]; then
echo "Une sauvegarde est déjà en cours. Quittez l'autre instance."
exit 1
fi
# Créer le lockfile
echo $$ > "$LOCKFILE"
# Corps du script
echo "Sauvegarde de $SOURCE vers $DEST..."
tar -czf "$DEST" "$SOURCE" && echo "Sauvegarde terminée : $DEST"
# Supprimer le lockfile avant de quitter (cleanup le fait, mais explicite)
rm -f "$LOCKFILE"
**Points clés de ce script :**
set -euo pipefail → arrêt sur erreur, variable manquante ou pipe cassétrap cleanup EXIT INT TERM → nettoyage systématique (lock + message)local exit_code=$?# Voir les signaux disponibles
kill -l
# Envoyer SIGTERM à un processus (demande polie)
kill -15 1234
# Envoyer SIGKILL (forcé)
kill -9 1234
# Envoyer un signal à tous les processus d'un nom
pkill -f "mon-script.sh"
#!/bin/bash
trap 'echo "Signal reçu !"' INT
echo "En attente... (Ctrl+C pour tester)"
while true; do
sleep 1
done
set| Option | Description |
|---|---|
set -e | Quitte si une commande échoue |
set -u | Quitte si une variable est indéfinie |
set -o pipefail | Quitte si une commande dans un pipe échoue |
set -x | Affiche chaque commande avant de l'exécuter (debug) |
set -n | Lit le script sans exécuter (syntax check only) |
Pour le debug, tu peux aussi utiliser bash -x mon-script.sh.
**Objectif :** Créer un script monitoring.sh qui surveille l'espace disque et qui :
1. Quitte proprement sur Ctrl+C (affiche un message d'au revoir)
2. Supprime son fichier lock à la sortie
3. Utilise set -euo pipefail
4. Vérifie l'espace disque et affiche une alerte si > 80%
#!/bin/bash
# Objectif : créer ce script
# 1. Ajouter set -euo pipefail
# 2. Créer un lockfile /tmp/monitoring.lock
# 3. Écrire une fonction cleanup() qui supprime le lock
# 4. Intercepter EXIT, INT, TERM
# 5. Vérifier l'espace disque : df / | grep -v Filesystem | awk '{print $5}' | tr -d '%'
# 6. Si > 80%, afficher "Alerte : espace disque faible !"
# 7. Boucle infinie avec sleep 10
**Solution indicative :**
#!/bin/bash
set -euo pipefail
LOCKFILE="/tmp/monitoring.lock"
cleanup() {
rm -f "$LOCKFILE"
echo "Script arrêté. Au revoir !"
}
trap cleanup EXIT INT TERM
if [ -f "$LOCKFILE" ]; then
echo "Le script tourne déjà."
exit 1
fi
echo $$ > "$LOCKFILE"
echo " Surveillance disque... (Ctrl+C pour arrêter)"
while true; do
usage=$(df / | tail -1 | awk '{print $5}' | tr -d '%')
if [ "$usage" -gt 80 ]; then
echo " Alerte : espace disque à ${usage}% !"
fi
sleep 10
done
| Concept | Commande / Outil | À retenir |
|---|---|---|
| Intercepter les signaux | trap 'fonction' SIG | Nettoyer les ressources à la sortie |
| Quitter sur erreur | set -e | Utile pour les scripts critiques |
| Quitter sur variable manquante | set -u | Évite les bugs silencieux |
| Pipe échecs | set -o pipefail | Détecte les erreurs dans les pipes |
| Code de sortie | $? | 0 = succès, != 0 = erreur |
| Debug | bash -x script.sh | Affiche chaque commande |
Un script qui gère ses signaux et ses erreurs, c'est un script **professionnel**. Même si ton serveur coupe, ton script aura le temps de nettoyer ses fichiers temporaires et de préserver ses données.