
Un script Bash peut laisser des fichiers temporaires derrière lui dès qu’une commande échoue ou qu’un utilisateur l’interrompt avec Ctrl+C. Sur un serveur, ces restes compliquent les diagnostics et peuvent finir par remplir un répertoire.
La combinaison mktemp + trap permet de supprimer ces fichiers à la sortie du script, y compris après une interruption. Il faut toutefois préserver le code de retour du script et éviter de masquer l’erreur d’origine.
Créer un temporaire que le script peut supprimer
Commencez par créer un fichier dans le répertoire temporaire du système. mktemp génère un nom unique et évite les collisions entre deux exécutions simultanées.
#!/usr/bin/env bash
set -u
tmp_file=$(mktemp)
echo "Fichier temporaire : $tmp_file"
printf '%sn' "données de test" > "$tmp_file"
cat "$tmp_file"
rm -f "$tmp_file"
Le nettoyage manuel fonctionne sur une sortie normale, mais il ne sera pas exécuté si une commande quitte brutalement le script ou si vous envoyez une interruption. C’est précisément le rôle de trap.
Nettoyer à la sortie avec trap EXIT
Le signal EXIT n’est pas un signal système classique. Bash l’utilise pour exécuter une fonction lorsque le script se termine, quel que soit le chemin de sortie atteint.
#!/usr/bin/env bash
set -u
tmp_file=$(mktemp)
cleanup() {
rm -f -- "$tmp_file"
}
trap cleanup EXIT
printf '%sn' "traitement en cours" > "$tmp_file"
cat "$tmp_file"
exit 0
Le fichier est supprimé après exit 0, mais aussi si une commande provoque une sortie anticipée. L’option -- indique à rm que le chemin qui suit ne doit pas être interprété comme une option.
Gérer une interruption sans perdre le code d’erreur
Pour un script lancé depuis un terminal, traitez aussi INT et TERM. Le piège consiste à remplacer le code de retour initial par celui de rm ou par un exit 0 placé dans le handler.
#!/usr/bin/env bash
set -u
tmp_file=$(mktemp)
cleanup() {
status=$?
trap - EXIT INT TERM
rm -f -- "$tmp_file"
exit "$status"
}
trap cleanup EXIT INT TERM
printf '%sn' "traitement en cours" > "$tmp_file"
sleep 30
printf '%sn' "traitement terminé"
exit 0
La variable $? est lue au début de cleanup, avant toute autre commande. Le script conserve ainsi son code de sortie, y compris après une erreur ou un arrêt demandé par le système.
Le trap - EXIT INT TERM évite de relancer le handler lorsque la fonction appelle elle-même exit. Si le script reçoit Ctrl+C, Bash nettoie le fichier puis sort avec le code associé à l’interruption. La syntaxe et les comportements détaillés sont documentés dans le manuel officiel de Bash.
Tester les trois sorties du script
Ne validez pas ce mécanisme sur le seul chemin nominal. Lancez le script normalement, provoquez une erreur, puis interrompez-le depuis un second terminal.
bash script.sh
printf 'code=%sn' "$?"
bash -c 'source ./script.sh'
bash script.sh &
pid=$!
kill -TERM "$pid"
wait "$pid"
printf 'code après TERM=%sn' "$?"
Après chaque test, relisez le dernier chemin journalisé et vérifiez qu’il n’existe plus :
last_path=$(tail -n 1 /tmp/script-cleanup.log | sed 's/^nettoyage : //')
test ! -e "$last_path" && echo "temporaire supprimé"
Une fois le test terminé, retirez la ligne de journal si le script ne doit pas conserver de trace locale. Dans un vrai script, vérifiez aussi que la variable a bien été initialisée avant de lancer rm. Si le temporaire contient des données sensibles, limitez sa durée de vie et ses permissions. Pour structurer les options d’un script Bash, vous pouvez compléter avec notre article sur getopts. Les commandes basename et dirname sont également utiles lorsque le nom du temporaire dépend d’un chemin construit par le script.