Определение имени принятого сигнала в Bash

Когда сигнал получен, я могу выполнить некоторые команды, используя trap, Пример:

trap 'echo hello world' 1 2

Если какой-либо из указанных сигналов получен, отображается "Привет, мир".

Но как я могу распечатать / идентифицировать имя полученного сигнала?

4 ответа

Решение

(Если у вас есть только номер сигнала и хотите имя, kill -l $SIGNAL_NUM печатает название сигнала; Вы можете избежать этого, используя имена сигналов вместо номеров в вашем звонке trap как ниже.)

Этот ответ говорит, что единственный способ определить, какой сигнал вы перехватили в bash, - это написать отдельную оболочку для каждого отдельного сигнала, который вы хотите перехватить. Другой ответ на тот же вопрос предоставляет вам функцию-обертку:

Код:

#!/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.

Если я запускаю это, то я могу отправлять сигналы процессу, и я получаю вывод, как

Trapped: INT
Trapped: TERM
Trapped: EXIT

В ловушке (при срабатывании через сигнал) $? переменная изначально установлена ​​на номер сигнала плюс 128, так что вы можете присвоить номер сигнала переменной, сделав первый оператор действия ловушки для чего-то вроде

sig=$(($? - 128))

Затем вы можете получить имя сигнала с помощью команды kill

kill -l $sig
for s in {1..64} ;do trap "echo trap $s" $s ;done

Или без баш-измов

s=1 ;while [ $s -le 64 ] ;do trap "echo trap $s" $s ;s=$((s+1)) ;done

Устанавливает 64 индивидуальных ловушки, по одной для каждого возможного сигнала.

Ссылаясь на $? Решение выше: $? будет отображать код завершения последней выполненной команды. Учти это:

#!/bin/bash
trap 'echo CODE: $?; exit 1' 1 2 3 15
sleep 3600

Если вы запустите это и нажмете Ctrl-C, он напечатает CODE: 130, Это потому что sleep исполняемый файл был прерван SIGINT и завершен с этим кодом.

Сравните это с:

#!/bin/bash
trap 'echo CODE: $?; exit 1' 1 2 3 15
read X

Если вы запустите это и нажмете Ctrl-C, он напечатает CODE: 0предположительно потому что read Команда является встроенной и правила кода выхода различны (то же самое происходит, если вы прервете while : ; do : ; done).

Так, $? только сообщает вам о сигнале, если он прервал внешнюю команду, и если эта конкретная программа не перехватила сигнал и не вышла со своим собственным кодом выхода. В этом случае сценарий bash приведен выше: после получения SIGINT он завершит работу с кодом 1не 130,

Простой способ сделать это:

_handler() {
   signal=$1
   echo signal was $signal
 }

 trap '_handler SIGTERM' SIGTERM
 trap '_handler SIGINT'  SIGINT
Другие вопросы по тегам