(Si solo tiene el número de una señal y quiere el nombre, kill -l $SIGNAL_NUM
imprime el nombre de una señal; puede evitar eso usando los nombres de las señales en lugar de los números en su llamada a trap
como se muestra a continuación.)
Esta respuesta dice que no hay forma de acceder al nombre de la señal, pero si tiene una función separada para cada señal que atrapa, entonces ya conoce el nombre de la señal:
trap 'echo trapped the HUP signal' HUP
trap 'echo different trap for the INT signal' INT
En muchos casos, eso puede ser suficiente, pero otra respuesta a la misma pregunta utiliza ese hecho para proporcionar una solución para simular el comportamiento que desea. Toma una función y una lista de señales y establece una trampa separada para cada señal en esa función llamada con el nombre de la señal, por lo que internamente en realidad es una función separada para cada señal, pero parece una sola trampa en una sola función que obtiene el nombre de la señal como argumento:
Código:
#!/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 ejecuto eso, entonces puedo enviar señales al proceso y obtengo un resultado como
Trapped: INT
Trapped: TERM
Trapped: EXIT
Haciendo referencia al $?
solución anterior:$?
reflejará el código de salida del último comando ejecutado. Considere esto:
#!/bin/bash
trap 'echo CODE: $?; exit 1' 1 2 3 15
sleep 3600
Si ejecuta esto y presiona Ctrl-C , imprimirá CODE: 130
. Eso es porque el sleep
el ejecutable fue interrumpido por SIGINT y salió con ese código.
Compara eso con:
#!/bin/bash
trap 'echo CODE: $?; exit 1' 1 2 3 15
read X
Si ejecuta esto y presiona Ctrl-C , imprimirá CODE: 0
, presumiblemente porque el read
El comando es un comando integrado y las reglas del código de salida son diferentes (lo mismo sucede si interrumpe while : ; do : ; done
).
Entonces, $?
solo le informa sobre la señal si interrumpió un comando externo, y si ese programa en particular no captó la señal y salió con su propio código de salida. El caso es el script bash anterior:al recibir un SIGINT, saldrá con el código 1
, no 130
.
Dentro de la trampa (cuando se activa a través de una señal), el $? La variable se establece inicialmente en el número de señal más 128, por lo que puede asignar el número de señal a una variable haciendo que la primera declaración de la acción de captura sea algo como
sig=$(($? - 128))
Luego puede obtener el nombre de la señal usando el comando matar
kill -l $sig
Actualización:como se indica en los comentarios, esto no funciona para algunos comandos de shell integrados. ¿Para que estos establezcan los $ de la trampa? variable, se pueden ejecutar en una subcapa, por ejemplo
(read)
en lugar de
read
una manera simple de hacer esto:
_handler() {
signal=$1
echo signal was $signal
}
trap '_handler SIGTERM' SIGTERM
trap '_handler SIGINT' SIGINT