GNU/Linux >> Tutoriales Linux >  >> Linux

Identificar el nombre de la señal recibida en Bash

(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

Linux
  1. 5 ejemplos de declaraciones de casos Bash

  2. Python - Atrapa todas las señales

  3. Ejecute el comando bash en la canalización de jenkins

  4. Mostrar solo el nombre del directorio actual (no la ruta completa) en el indicador de bash

  5. ¿Cómo desarmo o me deshago de una función bash?

Comando de espera bash

Golpear mientras se repite

Funciones bash

Bash Shebang

Comandos útiles de Bash que quizás no conozcas

Linux Bash Scripting Part5 – Señales y trabajos