выход из ловушки в dash против ksh и bash

выход из ловушки в dash против ksh и bash

Вот простой скрипт, который создает временный каталог в текущем каталоге и ловушку для его удаления при выходе.

#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в упомянутом вами случае, очевидно, что вы вводитенеопределенныеповедение.

Связанный контент