> touch tmp/foo/bar/baz
> rename baz boo tmp/foo/bar/baz
> ls -l tmp/foo/bar/
total 0
-rw-r--r-- 1 hl hauke 0 May 29 23:08 boo
zsh
, pdksh
(хотя и не последние версии mksh
, производные от него), yash
, Bourne shell ведут себя как dash
.
Только bash
, ksh88
, ksh93
и mksh
ведут себя иначе.
В спецификации POSIX нет ясности относительно того, каким должно быть правильное поведение, но там ничего не говорится о том, что оболочке разрешено переопределять обработчик по умолчанию для сигнала SIGINT (или другого).
Там говорится, что действие ловушки EXIT должно оцениваться, когда вызывается exit
, но, AFAICT, там даже не сказано, например, должна ли она оцениваться, когда оболочка выходит в результате set -e
или set -u
или при ошибках, таких как синтаксические ошибки или сбой специальных встроенных модулей.
Чтобы иметь возможность запускать ловушку EXIT при получении сигнала, оболочка должна установить обработчик этого сигнала.
Именно это делают ksh
, mksh
и bash
, но список сигналов, которые они обрабатывают, отличается во всех трех реализациях. Единственными сигналами, общими для всех трех, являются 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
работает корректно, если вызывается несколько раз, и/или игнорировать сигналы во время ее выполнения.
Предупреждение: exit
не гарантируется, вы должны вместо этого использовать EXIT
Учитывая, что стандарт POSIX поддерживает не определяет, должна ли ловушка EXIT
также выполняться в случае сигнала, и учитывая тот факт, что Bourne Shell не вызывает ловушку EXIT
в указанном вами случае, это очевидно что вы вводите неопределенное поведение.