Нужно ли указывать ловушки, кроме EXIT?
Я вижу много скриптов оболочки:
trap cmd 0 1 2 3 13 15 # EXIT HUP INT QUIT PIPE TERM
В каждой оболочке, к которой у меня есть доступ в данный момент, все ловушки, отличные от 0, являются избыточными, а cmd будет выполняться после получения сигнала, если просто указывается ловушка:
trap cmd 0
Является ли последняя спецификация достаточной или для некоторых оболочек требуются другие сигналы?
Ответы
Ответ 1
Чтобы убедиться, что обработчик сигнала EXIT
не будет выполняться дважды (что почти всегда не так, как вы хотите), он всегда должен быть проигнорирован или reset в определении самого обработчика сигнала 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
Ответ 2
Я думаю, что trap 0 выполняется как раз перед завершением script во всех случаях, поэтому полезно для функций очистки (например, удаление временных файлов и т.д.). Другие сигналы могут иметь специализированную обработку ошибок, но должны завершать script (т.е. Вызывать вызов).
То, что вы описали, я считаю, фактически выполнило бы cmd дважды. Один раз для сигнала (например, SIGTERM) и еще раз при выходе (trap 0).
Я считаю, что правильный способ сделать это выглядит следующим образом (см. спецификацию POSIX для trap
):
trap "rm tmpfile" 0
trap "exit 1" TERM HUP ...
Это гарантирует, что временный файл будет удален после завершения script, и позволит вам устанавливать пользовательские статусы выхода на сигналы.
ПРИМЕЧАНИЕ: ловушка 0 вызывается, встречен ли сигнал или нет.
Если вам не нужно устанавливать статус выхода, ловушка 0 будет достаточной.
Ответ 3
В стандарте оболочки не указывается, выполняется ли ловушка на 0 при получении незахваченного сигнала. В частности, bash и тире ведут себя по-разному. Учитывая trap cmd-list 0
без каких-либо ловушек, установленных для любых сигналов, bash выполнит список cmd после получения SIGTERM, но тире не будет. Учитывая trap cmd-list 0 2
, bash выполняет cmd-list один раз после получения SIGTERM, а dash выполняет cmd-list дважды.