Определение имени принятого сигнала в 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