Вот простой скрипт, который создает временный каталог в текущем каталоге и ловушку для его удаления при выходе.
#filename: script
set -x
trap 'rm -rf "$d"' exit
d=`TMPDIR=$PWD mktemp -d`
"$@"
Если я делаю ksh script sleep 100
или bash script sleep 100
и прерываю его с помощью, C-C
, ловушка выполняется и каталог удаляется. Это не работает с dash
. Почему? Это ошибка или задуманное поведение?
решение1
zsh
, pdksh
(хотя и не последние версии, mksh
производные от этого) yash
, оболочка Bourne ведет себя как dash
.
Только bash
, ksh88
, ksh93
и mksh
ведут себя иначе.
В спецификации POSIX нет четкого определения правильного поведения, но в ней нет ничего, что говорило бы о том, что оболочке разрешено переопределять обработчик по умолчанию для сигнала SIGINT
(или другого сигнала).
В нем говорится, что EXIT
действие ловушки должно быть оценено при exit
вызове, но, насколько мне известно, в нем даже не говорится, например, должно ли оно быть оценено при выходе из оболочки в результате set -e
или set -u
из-за ошибочных условий, таких как синтаксические ошибки или сбой специальных встроенных функций.
Чтобы иметь возможность запускать EXIT
ловушку при получении сигнала, оболочке необходимо установить обработчик этого сигнала.
Это то , что делают ksh
, mksh
и bash
, но список сигналов, которые они обрабатывают, отличается во всех трех реализациях. Единственными общими сигналами для всех 3, похоже, являются INT
, QUIT
, TERM
, ALRM
и HUP
.
Если вы хотите, EXIT
чтобы ловушка запускалась при наличии каких-либо сигналов, переносимым способом будет обработка этих сигналов самостоятельно:
trap 'exit 1' INT HUP QUIT TERM ALRM USR1
trap 'cleanup' EXIT
Однако этот подход не работает с zsh
, который не запускает EXIT
ловушку, если exit
вызывается из обработчика ловушек.
Он также не сообщает родителям о вашей смерти посредством сигнала.
Поэтому вместо этого вы можете сделать следующее:
for sig in INT QUIT HUP TERM ALRM USR1; do
trap "
cleanup
trap - $sig EXIT
kill -s $sig "'"$$"' "$sig"
done
trap cleanup EXIT
Теперь, будьте осторожны, если во время выполнения поступит больше сигналов cleanup
, cleanup
может быть запущен снова. Вы можете убедиться, что cleanup
работает правильно, если вызывается несколько раз и/или игнорировать сигналы во время выполнения.
решение2
Предупреждение: exit
работа не гарантируется, вместо этого следует использоватьEXIT
Учитывая, что стандарт POSIX не определяет, EXIT
должна ли ловушка также выполняться в случае сигнала, и учитывая тот факт, что Bourne Shell не вызывает ловушку EXIT
в упомянутом вами случае, очевидно, что вы вводитенеопределенныеповедение.