(Si vous n'avez que le numéro d'un signal et que vous voulez le nom, kill -l $SIGNAL_NUM
imprime le nom d'un signal ; vous pouvez éviter cela en utilisant les noms des signaux au lieu des numéros dans votre appel au trap
comme ci-dessous.)
Cette réponse indique qu'il n'y a aucun moyen d'accéder au nom du signal, mais si vous avez une fonction distincte pour chaque signal que vous piègez, vous connaissez déjà le nom du signal :
trap 'echo trapped the HUP signal' HUP
trap 'echo different trap for the INT signal' INT
Dans de nombreux cas, cela peut être suffisant, mais une autre réponse à cette même question utilise ce fait pour fournir une solution de contournement pour simuler le comportement souhaité. Il prend une fonction et une liste de signaux et définit un piège séparé pour chaque signal sur cette fonction appelée avec le nom du signal, donc en interne, c'est en fait une fonction distincte pour chaque signal, mais cela ressemble à un seul piège sur une seule fonction qui obtient le nom du signal en argument :
Code :
#!/bin/bash
trap_with_arg() {
func="$1" ; shift
for sig ; do
trap "$func $sig" "$sig"
done
}
func_trap() {
echo "Trapped: $1"
}
trap_with_arg func_trap INT TERM EXIT
echo "Send signals to PID $$ and type [enter] when done."
read # Wait so the script doesn't exit.
Si je l'exécute, je peux envoyer des signaux au processus et j'obtiens une sortie comme
Trapped: INT
Trapped: TERM
Trapped: EXIT
Se référant au $?
solution ci-dessus :$?
reflétera le code de sortie de la dernière commande exécutée. Considérez ceci :
#!/bin/bash
trap 'echo CODE: $?; exit 1' 1 2 3 15
sleep 3600
Si vous lancez ceci et appuyez sur Ctrl-C , il imprimera CODE: 130
. C'est parce que le sleep
l'exécutable a été interrompu par le SIGINT et s'est terminé avec ce code.
Comparez cela à :
#!/bin/bash
trap 'echo CODE: $?; exit 1' 1 2 3 15
read X
Si vous lancez ceci et appuyez sur Ctrl-C , il imprimera CODE: 0
, probablement parce que le read
la commande est intégrée et les règles de code de sortie sont différentes (la même chose se produit si vous interrompez while : ; do : ; done
).
Alors, $?
ne vous informe du signal que s'il a interrompu une commande externe, et si ce programme particulier n'a pas capté le signal et est sorti avec son propre code de sortie. Le point au cas où est le script bash ci-dessus :lors de la réception d'un SIGINT, il se terminera avec le code 1
, pas 130
.
Dans le piège (lorsqu'il est déclenché via un signal), le $ ? variable est initialement définie sur le numéro de signal plus 128, vous pouvez donc affecter le numéro de signal à une variable en faisant la première déclaration de l'action de déroutement à quelque chose comme
sig=$(($? - 128))
Vous pouvez ensuite obtenir le nom du signal en utilisant la commande kill
kill -l $sig
Mise à jour :comme indiqué dans les commentaires, cela ne fonctionne pas pour certaines commandes shell intégrées. Pour que ceux-ci fixent les $ du piège ? variable, ils peuvent être exécutés dans un sous-shell, par exemple
(read)
au lieu de
read
un moyen simple de le faire :
_handler() {
signal=$1
echo signal was $signal
}
trap '_handler SIGTERM' SIGTERM
trap '_handler SIGINT' SIGINT