========================================================= Commandes Bash : Chapitre sur **Trap**, controle du flux ========================================================= .. contents:: :depth: 2 :local: :backlinks: top **Intro:** ---------- La commande `trap` permet d’exécuter des actions spécifiques lorsqu’un signal est capturé ou lorsqu’un événement particulier survient dans un script Bash. --- **Principe :** -------------- - `trap` intercepte un **signal** (par ex. : `SIGINT` pour Ctrl+C) ou un **événement** (par ex. : `ERR` pour une erreur) et exécute une commande ou un bloc de code. - Cela permet de gérer les interruptions, d'effectuer des nettoyages ou de réagir à des erreurs. **Syntaxe :** ------------- .. code-block:: bash trap 'commande' signal - **`commande`** : La commande ou le code à exécuter lors de la réception du signal. - **`signal`** : Le signal ou l’événement à surveiller (par exemple, `EXIT`, `ERR`, `SIGINT`). --- **Capture des erreurs avec `ERR` :** ------------------------------------ - `trap ERR` détecte automatiquement les erreurs des commandes qui retournent un code de sortie non nul. - Lorsque `ERR` est déclenché, `trap` exécute la commande ou le bloc défini. **Exemple simplifié :** .. code-block:: bash trap 'echo "Une erreur est survenue."' ERR echo "Début du script." cp fichier_inexistant.txt /tmp # Cette commande échoue echo "Cette ligne est exécutée si set -e n'est pas activé." **Explication :** 1. **Déclaration du `trap` :** - Dès qu’une commande échoue, `trap ERR` exécute `echo "Une erreur est survenue."`. 2. **Échec de la commande `cp` :** - `cp` tente de copier un fichier inexistant, ce qui provoque une erreur (code de sortie non nul). - L’événement `ERR` est déclenché, et le message d’erreur défini dans `trap` est affiché. 3. **Conséquence :** - Si `set -e` est activé, le script s'arrête après l'exécution de la commande `trap`. - Si `set -e` n'est pas activé, la commande suivante continue de s'exécuter. --- **Gestion des signaux système :** --------------------------------- - `trap` peut capturer des signaux système spécifiques pour gérer des interruptions extérieures au script. - **`SIGINT`** : Interruption manuelle via Ctrl+C. - **`SIGTERM`** : Arrêt demandé par un autre processus. - **`SIGHUP`** : Déconnexion de la session terminal. **Exemple : Interception de Ctrl+C (`SIGINT`)** .. code-block:: bash trap 'echo "Interruption détectée. Le script ne sera pas interrompu."' SIGINT while true; do echo "Travail en cours..." sleep 1 done **Explication :** 1. Lorsque l’utilisateur appuie sur Ctrl+C, le signal `SIGINT` est intercepté. 2. Au lieu de stopper le script, le message `"Interruption détectée. Le script ne sera pas interrompu."` est affiché. 3. La boucle continue de s’exécuter normalement. --- **Nettoyage avec `EXIT` :** --------------------------- - `trap EXIT` exécute une commande ou un bloc de code à la fin de l’exécution du script. - Cela s’applique même si le script se termine suite à une erreur ou un `exit`. **Exemple : Gestion de fichiers temporaires** .. code-block:: bash trap 'rm -rf /tmp/tempfile; echo "Nettoyage terminé."' EXIT echo "Création d’un fichier temporaire." touch /tmp/tempfile echo "Fichier temporaire créé : /tmp/tempfile" echo "Fin du script." **Explication :** 1. **Déclaration du `trap` :** - À la fin du script (signal `EXIT`), la commande `rm -rf /tmp/tempfile` est exécutée pour supprimer le fichier temporaire. 2. **Création du fichier temporaire :** - Le script crée un fichier temporaire avec `touch /tmp/tempfile`. 3. **Nettoyage automatique :** - Une fois le script terminé, le `trap EXIT` supprime le fichier temporaire et affiche le message `"Nettoyage terminé."`. --- **Sous-shells et `trap ERR` :** ------------------------------- - `trap ERR` ne capture pas les erreurs dans les sous-shells. Les commandes exécutées dans des sous-shells (par exemple, avec `$(...)` ou `(commandes)`) ne déclenchent pas `ERR`. **Exemple :** .. code-block:: bash trap 'echo "Erreur détectée."' ERR echo $(ls fichier_inexistant.txt) # Pas capturé par trap ERR **Explication :** 1. `ls fichier_inexistant.txt` échoue dans un sous-shell (car il est dans `$()`). 2. `trap ERR` ne détecte pas cette erreur. --- **Blocs conditionnels et `trap ERR` :** --------------------------------------- - Les erreurs dans des blocs conditionnels (comme `if` ou `while`) ne déclenchent pas `trap ERR`, car ces contextes évaluent volontairement l’état de la commande. **Exemple :** .. code-block:: bash trap 'echo "Erreur capturée."' ERR if ls fichier_inexistant.txt; then echo "Fichier trouvé." fi # L'erreur de ls n'est pas capturée par trap ERR **Explication :** 1. `ls fichier_inexistant.txt` échoue, mais l’erreur est évaluée dans le contexte du `if`. 2. `trap ERR` n’est pas déclenché dans ce cas. --- **Résumé des signaux courants :** --------------------------------- - **`ERR`** : Détecte les erreurs des commandes Bash (hors sous-shells ou conditionnels). - **`EXIT`** : Exécute une commande à la fin du script. - **`SIGINT`** : Intercepte une interruption par Ctrl+C. - **`SIGTERM`** : Capture une demande d’arrêt envoyée par un processus. - **`SIGHUP`** : Réagit à une déconnexion du terminal.