GNU/Linux >> Tutoriels Linux >  >> Linux

Identification du nom du signal reçu dans Bash

(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

Linux
  1. 5 exemples d'instructions Bash Case

  2. Comment connaître le nom du fichier de script dans un script Bash ?

  3. Python - Piège tous les signaux

  4. BASH :envoie le signal SIGTSTP (ctrl+z)

  5. Exécutez la commande bash sur le pipeline jenkins

Commande d'attente bash

Bash pendant la boucle

Fonctions bash

Bash Shebang

Commandes Bash utiles que vous ne connaissez peut-être pas

Linux Bash Scripting Part5 - Signaux et tâches