Trap

De wiki.nexiat.fr
Aller à la navigation Aller à la recherche
Fiche express
Domaine Shell scripting, gestion des signaux
Commande trap
Contexte Builtin bash — intercepter ou ignorer un signal reçu par un script
Voir aussi Signal (liste des signaux), Kill (envoi de signaux)

trap est un builtin du shell (bash, sh) qui permet d'exécuter une commande ou une fonction lorsqu'un script reçoit un signal donné, au lieu de subir le comportement par défaut de ce signal (terminaison, arrêt, etc.). C'est le mécanisme standard pour garantir un nettoyage propre (suppression de fichiers temporaires, libération de verrous, affichage d'un message) même si le script est interrompu par Ctrl-C ou tué proprement.

Syntaxe de base

trap 'commande' SIGNAL          # exécute 'commande' à la réception de SIGNAL
trap 'commande' SIGNAL1 SIGNAL2 # plusieurs signaux pour la même commande
trap -l                         # liste les noms de signaux connus du shell
trap -p                         # affiche les traps actuellement définis
trap - SIGNAL                   # restaure le comportement par défaut de SIGNAL

Le nom du signal peut être donné avec ou sans le préfixe SIG (INT ou SIGINT), et un numéro fonctionne aussi (2 pour SIGINT) — la liste complète des signaux est détaillée dans Signal.

Ignorer un signal

Une commande vide ignore purement et simplement le signal : le script continue son exécution sans interruption ni action particulière.

trap '' SIGNAL     # ignore SIGNAL (aucune action, le signal est avalé)
trap '' INT        # le script devient insensible à Ctrl-C
trap '' HUP        # le script survit à la fermeture du terminal qui l'a lancé

⚠️ Un trap vide hérité par un sous-processus (fork) reste actif dans ce sous-processus, contrairement à un trap avec une vraie commande qui, lui, est réinitialisé au comportement par défaut après un exec.

Intercepter Ctrl-C (SIGINT)

Exemple classique : intercepter Ctrl-C pour afficher un message avant de quitter, plutôt que de laisser bash tuer le script brutalement.

#!/bin/bash

ctrl_c()
{
    echo "** Trapped CTRL-C"
}

trap ctrl_c INT

f()
{
    for i in $(seq 1 100); do
        sleep 1
        echo -n "."
    done
}

f

Ici trap appelle la fonction ctrl_c (définie avant l'appel à trap, l'ordre compte) chaque fois que le script reçoit SIGINT — la boucle de la fonction f continue ensuite tant qu'aucun exit n'est ajouté dans ctrl_c.

Nettoyage sur plusieurs signaux

Cas courant : intercepter plusieurs signaux de terminaison pour exécuter le même nettoyage avant de quitter, quelle que soit la cause de l'interruption.

trap 'echo "$0 (PID $$) tué le $(date)."; exit' HUP INT QUIT ABRT TERM
  • HUP — terminal fermé ou déconnecté
  • INT — Ctrl-C
  • QUIT — Ctrl-\
  • ABRT — arrêt anormal (souvent déclenché par le programme lui-même)
  • TERM — signal de terminaison par défaut de kill

Un exit explicite est nécessaire à la fin de la commande sinon le script reprend son exécution normale après avoir traité le signal.

Nettoyage garanti de fichiers temporaires

Le cas d'usage le plus fréquent de trap : garantir la suppression d'un fichier temporaire même si le script est interrompu en cours de route, sans dupliquer le nettoyage à chaque point de sortie possible.

tmpfile=$(mktemp)
trap 'rm -f "$tmpfile"' EXIT

# ... traitement utilisant $tmpfile ...

EXIT n'est pas un vrai signal Unix mais un pseudo-signal bash : le trap se déclenche à toute sortie du script, qu'elle soit normale (fin du script, exit explicite) ou provoquée par un signal intercepté ailleurs — c'est la méthode la plus sûre pour ne jamais laisser de fichier temporaire orphelin.

Voir aussi

  • Signal — liste des signaux Unix et leur signification
  • Kill — envoi de signaux à un processus