linux - tag - bash traduccion
Identificando el nombre de la señal recibida en Bash (4)
(Si solo tiene el número de una señal y desea el nombre, kill -l $SIGNAL_NUM
imprime el nombre de una señal; puede evitarlo usando los nombres de las señales en lugar de los números de su llamada para trap
como se muestra a continuación).
Esta respuesta dice que la única manera de identificar qué señal atrapó en bash es escribir un envoltorio separado para cada señal diferente que desea atrapar. Otra respuesta a esa misma pregunta proporciona una función de envoltorio para que lo haga por usted:
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
read # Wait so the script doesn''t exit.
Si ejecuto eso, entonces puedo enviar señales al proceso y obtengo una salida como
Trapped: INT
Trapped: TERM
Trapped: EXIT
Cuando se recibe una señal, puedo ejecutar algunos comandos utilizando la trap
. Ejemplo:
trap ''echo hello world'' 1 2
Si se recibe alguna de las señales especificadas, se muestra "hola mundo".
Pero, ¿cómo puedo imprimir / identificar el nombre de la señal recibida?
Dentro de la trampa (cuando se dispara 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 a algo como
sig=$(($? - 128))
A continuación, puede obtener el nombre de la señal utilizando el comando kill
kill -l $sig
Refiriéndose a los $?
solución anterior: $?
reflejará el código de salida del último comando ejecutado. Considera esto:
#!/bin/bash
trap ''echo CODE: $?; exit 1'' 1 2 3 15
sleep 3600
Si ejecuta esto y presiona Ctrl-C , se imprimirá el CODE: 130
. Eso es porque el ejecutable de sleep
fue interrumpido por el 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 , se imprimirá el CODE: 0
, presumiblemente porque el comando de read
es un código integrado y las reglas del código de salida son diferentes (lo mismo sucede si usted interrumpiera while : ; do : ; done
).
Entonces, $?
solo le informa sobre la señal si interrumpió un comando externo, y si ese programa en particular no ha captado la señal y ha salido con su propio código de salida. El punto en el caso es el script de bash anterior: al recibir un SIGINT, saldrá con el código 1
, no 130
.
Una forma sencilla de hacer esto:
_handler() {
signal=$1
echo signal was $signal
}
trap ''_handler SIGTERM'' SIGTERM
trap ''_handler SIGINT'' SIGINT