Нужно ли указывать ловушки кроме EXIT? - PullRequest
31 голосов
/ 14 ноября 2011

Я вижу много сценариев оболочки, которые делают:

trap cmd 0 1 2 3 13 15 # EXIT HUP INT QUIT PIPE TERM

В каждой оболочке, к которой у меня есть доступ в настоящий момент, все ловушки, кроме 0, избыточны, и cmd будет выполняться при получении сигнала, если ловушка просто указана:

trap cmd 0

Является ли последняя спецификация достаточной или некоторые оболочки требуют указания других сигналов?

Ответы [ 3 ]

20 голосов
/ 11 февраля 2013

Чтобы убедиться, что обработчик сигнала EXIT не будет выполнен дважды (что почти всегда не то, что вам нужно), его всегда следует игнорировать или сбрасывать в рамках определения самого обработчика сигнала EXIT.

То же самое относится к сигналам, для которых в программе определено более одного обработчика сигналов.

# reset
trap 'excode=$?; cmd; trap - EXIT; echo $excode' EXIT HUP INT QUIT PIPE TERM

# ignore
trap 'excode=$?; trap "" EXIT; cmd; echo $excode' EXIT HUP INT QUIT PIPE TERM
18 голосов
/ 14 ноября 2011

Я думаю, что прерывание 0 выполняется непосредственно перед завершением сценария во всех случаях, поэтому полезно для очистки (например, удаление временных файлов и т. Д.). Другие сигналы могут иметь специальную обработку ошибок, но должны завершать сценарий (то есть вызывать выход).

То, что вы описали, я полагаю, на самом деле выполнит cmd дважды. Один раз для сигнала (например, SIGTERM) и еще раз для выхода (ловушка 0).

Я считаю, что правильный способ сделать это выглядит следующим образом (см. Спецификацию POSIX для trap):

trap "rm tmpfile" 0
trap "exit 1" TERM HUP ... 

Это гарантирует, что временный файл будет удален после завершения скрипта, и позволяет вам устанавливать собственные состояния выхода для сигналов.

ПРИМЕЧАНИЕ : ловушка 0 вызывается независимо от того, встречается сигнал или нет.

Если вас не интересует настройка статуса выхода, будет достаточно ловушки 0.

6 голосов
/ 18 октября 2012

Стандарт оболочки не определяет, будет ли выполняться ловушка на 0 при получении необработанного сигнала. В частности, bash и dash ведут себя по-разному. Учитывая trap cmd-list 0 без каких-либо ловушек, установленных для каких-либо сигналов, bash выполнит cmd-список при получении SIGTERM, но dash - нет. С учетом trap cmd-list 0 2 bash выполняет cmd-список один раз после получения SIGTERM, а dash выполняет cmd-список дважды.

...