Родительская ловушка видима, но не запускается подоболочкой
Протестировано на Bash 5.0.2
Согласно справочному руководству GNU Bash,
Bash выполняет расширение [подстановки команд], выполняя команду [] в среде подоболочек
В соответствии с Открытой группой Базовые спецификации, выпуск 6:
при вводе подоболочки для ловушек, которые не игнорируются, устанавливаются действия по умолчанию.
Так что при запуске следующего скрипта:
function a {
trap -p EXIT
}
trap "echo 'parent'" EXIT
echo "$(a)"
(a)
trap - EXIT
echo 'exiting'
... я бы ожидал вывод:
exiting
... но вместо этого я получаю:
trap -- 'echo '\''parent'\''' EXIT
trap -- 'echo '\''parent'\''' EXIT
exiting
... это означает, что функция a
- несмотря на то, что он запускается в подоболочке - видит команды перехвата родительской оболочки (через trap -p
) но не выполняет их.
Что здесь происходит?
2 ответа
Вы заметите, что ловушки срабатывают точно в соответствии со спецификацией. Это просто вывод из trap
это неожиданно
Это особенность Bash 4.2 ( примечания к выпуску):
b. Subshells begun to execute command substitutions or run shell functions or
builtins in subshells do not reset trap strings until a new trap is
specified. This allows $(trap) to display the caller's traps and the
trap strings to persist until a new trap is set.
Обычно люди воспринимают это как должное. Считайте, что это совершенно неудивительно, обмен Bash:
bash$ trap
trap -- 'foo' EXIT
trap -- 'bar' SIGINT
bash$ trap | grep EXIT
trap -- 'foo' EXIT
Теперь посмотрим на результат в других оболочках, таких как Dash, Ksh или Zsh:
dash$ trap
trap -- 'foo' EXIT
trap -- 'bar' INT
dash$ trap | grep EXIT
(no output)
Возможно, это более правильно, но я сомневаюсь, что многие ожидают этого.
Вы, кажется, читаете старую версию спецификации. В самой последней
Когда вводится подоболочка, для ловушек, которые не игнорируются, должны быть установлены действия по умолчанию, за исключением случая замены команды, содержащей только одну команду ловушек, когда ловушки не нужно изменять.