Lorsqu'un shell UNIX s'achève soit de lui-même soit par une erreur (interuption par ctrl+C, une erreur de syntaxe ou de commande, ...) il se peut que les répertoires ne soient pas propres ou remis en état.
En effet, surtout dans le cas d'une fin en erreur, en fonction de l'endroit où le script s'est arrêté, les générations de fichiers et/ou de données n'étant pas finies, tout n'est pas forcément propre et cohérent. Dan certains cas, il peut même être utile d'exécuter un autre script en cas d'erreur afin, par exemple, d'envoyer un message d'alerte, effectuer une restauration ou une sauvegarde, ...
Malheureusement,pour réaliser tout cela il faut pouvoir réagir en fonction du type d'arrêt de script. trap est la commande qui permet justement de faire cela.
trap 'commande' liste_de_signaux
Le numéro de signal correspond à ceux qu'on obtient avec la commande kill -l. Avec trap on peut soit utiliser le signal, soit son numéro.
# kill -l 1) HUP 23) WINCH 2) INT 24) STOP 3) QUIT 25) TSTP 4) ILL 26) CONT 5) TRAP 27) TTIN 6) IOT 28) TTOU 7) EMT 29) URG 8) FPE 30) LOST 9) KILL 31) RESERVED 10) BUS 32) DIL 11) SEGV 33) XCPU 12) SYS 34) XFSZ 13) PIPE 35) bad trap 14) ALRM 36) bad trap 15) TERM 37) RTMIN 16) USR1 38) RTMIN+1 17) USR2 39) RTMIN+2 18) CHLD 40) RTMIN+3 19) PWR 41) RTMAX-3 20) VTALRM 42) RTMAX-2 21) PROF 43) RTMAX-1 22) POLL 44) RTMAX
| Signal | Signification |
|---|---|
| HUP | hangup : envoie un signal de réinitialisation |
| INT | Interruption |
| QUIT | Core dump |
| ILL | Le programme tente d'exécuter du code malformé, inconnu ou avec de mauvais privilèges |
| TRAP | Le programme envoie un signal au débugger (message capturé) |
| IOT | idem SIGABRT : interruption du programme |
| EMT | emulator trap : un programme émulé ou virtualisé a posé problème |
| FPE | floating-point exception : le programme a réalisé une opération arithmétique erronée |
| KILL | arrête le programme immédiatement |
| BUS | Le programme a causé une erreur de bus |
| SEGV | Segmentation fault : le programme fait référence à un mauvais emplacement de mémoire |
| SYS | Un mauvais argument est passé en paramètre |
| PIPE | Un programme tente d'écrire dans un pipe sans processus connecté à l'autre bout |
| ALRM | La limite de temps est dépassée |
| TERM | Envoie un signal au programme pour le terminer |
| USR1/USR2 | Envoie un signal dans des conditions définies par un utilisateur |
| CHLD/CLD | child : signal envoyé par un programme lorsqu'un processus fils est achevé |
| PWR | power : le système subit un problème d'alimentation |
| VTALRM | virtual alarm : signal envoyé lorsque le temps limite a été dépassé |
| PROF | profiler : signal envoyé lorsqu'un timer a expiré |
| POLL | polling : un problème est survenu lors d'un événement I/O asynchrone |
| WINCH | window [size] change : signal envoyé au programme lorsque la fenêtre de contrôle change de taille |
| STOP | signal demandant au programme de se suspendre |
| TSTP | tty stop : signal envoyé au programme lorsqu'un terminal suspend ses requêtes |
| CONT | Redémarre un programme suspendu par STOP |
| TTIN | Le programme tente de lire tty alors qu'il est en arrière-plan |
| TTOU | Le programme tente d'écrire sur tty alors qu'il est en arrière-plan |
| URG | Un socket a une donnée urgente à lire |
| LOST | Le verrou d'un fichier a été perdu |
| XCPU | Le programme a utilisé le CPU prend trop longtemps |
| XFSZ | Le fichier a dépassé la taille maximale autorisée |
| RTMIN/RTMIN+n | real-time minimum : signaux définis par l'application |
| RTMAX/RTMAX-n | real-time maximum : signaux définis par l'application |
Il existe aussi des pseudo signaux comme le signal 0 (EXIT) qui est la valeur retournée par la fin sans erreur d'un script. C'est aussi la valeur retournée par le shell lors de la déconnexion.
La commande est soit une (liste de) commande(s) exécutée(s) en direct soit un appel de fonction.
Le commande trap sert dans deux cas bien distincts :
trap "echo FIN; exit 0" 2 3 15
trap "" 1 2 3 15 # ignorer les signaux commande ... trap 1 2 3 15 # revenir à l'état par défaut
#!/bin/sh
trap "" 2 3 15 # ignorer les signaux
while :
do
echo "Entrez le mot de passe : \c"
read mdp
if [ "${mdp}" = "test" ]
then
echo "mot de passe valide !"
break
fi
done
trap 2 3 15 # revenir à l'état par défaut
Cet exemple montre que la boucle ne peut pas être interrompue, sauf par l'entrée du bon mot de passe. En effet, le script commence par mettre de côté les signaux en leur affectant une exécution vide. trap ne remettra en place correcte le contexte qui si la boucle s'achève avec succès (entrée du bon mot de passe). Ainsi, l'utilisateur, quoi qu'il fasse ne peut pas interrompre le programme.
trap "" 2 # ignorer le signal
trap "" 2 3 15 # ignorer les signaux
trap 2 # retablir la situation
trap "echo CTRL-C" INT # retablir la situation
Pour exécuter un script automatiquement à la déconnexion, il faut d'abord ajouter au fichier .profile :
trap "~/logoff" 0
Puis créer le script logoff en question :
#!/bin/sh rm /tmp/*.tmp clear echo "Suppression des fichiers temporaires terminée" echo "Déconnexion..."
Ne pas oublier de rendre le script exécutable...