Ловушка выхода в тире против ksh и bash

> 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
5
04.11.2015, 14:21
2 ответа

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 работает корректно, если вызывается несколько раз, и/или игнорировать сигналы во время ее выполнения.

15
27.01.2020, 20:32

Предупреждение: exit не гарантируется, вы должны вместо этого использовать EXIT

Учитывая, что стандарт POSIX поддерживает не определяет, должна ли ловушка EXIT также выполняться в случае сигнала, и учитывая тот факт, что Bourne Shell не вызывает ловушку EXIT в указанном вами случае, это очевидно что вы вводите неопределенное поведение.

1
27.01.2020, 20:32

Теги

Похожие вопросы