Ловушка наследуется подоболочкой?


14

Я попробовал следующий скрипт:

#!/bin/bash
trap 'echo "touching a file" && touch $FILE' EXIT

foo1(){
        echo "foo1"
}
foo(){
        echo "foo"
        export FILE=${FILE:-/tmp/file1}
}
(foo1)
foo

Выход для вышеуказанного скрипта был:

[root@usr1 my_tests]# ./test.sh
foo1
foo
touching a file

Однако я ожидал, что trap-сообщение также будет вызвано при выходе из foo1, что называется в подоболочке.

  • Это ожидается?
  • Является ли trapнаследоваться субоболочкой?
  • Если да, то в каком случае trapнаследуется подоболочка?

Ответы:


10

Обработчики ловушек никогда не наследуются подоболочками. Это указано в POSIX :

Когда вводится подоболочка, для ловушек, которые не игнорируются, устанавливаются действия по умолчанию.

Обратите внимание, что игнорируемые сигналы ( trap '' SIGFOO) остаются игнорируемыми в подоболочке (и во внешних программах, запускаемых оболочкой, тоже).


3
В bash вы можете set -Eдля того, чтобы подоболочки наследовали ловушки, но ДЕЙСТВИТЕЛЬНО сложно получить права (по крайней мере, по моему опыту).
dragon788

Я не знаю, работает ли это для всех ловушек. Я знаю, что это работает для ERR
yosefrow

4

trapне распространяется на подоболочки, но некоторые способы позволяют подоболочке сообщать о ловушках родительской оболочки, а другие - нет. Я сделал несколько тестов на MacOS с Bash.

GNU bash, версия 4.4.12 (1) -релиз (x86_64-apple-darwin16.3.0):

trap 'echo hello' EXIT
trap # trap -- 'echo hello' EXIT
echo "$(trap)" # trap -- 'echo hello' EXIT
trap | cat # trap -- 'echo hello' EXIT
(trap) | cat # trap -- 'echo hello' EXIT
cat < <(trap) # empty
cat <<< "$(trap)" # empty
bash -c 'trap' # empty
trap & # trap -- 'echo hello' EXIT

GNU bash, версия 3.2.57 (1) -релиз (x86_64-apple-darwin16):

trap 'echo hello' EXIT
trap # trap -- 'echo hello' EXIT
echo "$(trap)" # trap -- 'echo hello' EXIT
trap > >(cat) # trap -- 'echo hello' EXIT
trap | cat # empty
(trap) | cat # empty
cat < <(trap) # empty
cat <<< "$(trap)" # empty
bash -c 'trap' # empty
trap & # empty

Это хорошо знать, что trap_output="$(trap)"это сработает для захвата вывода ловушек. Я не могу придумать другого способа сделать это, если это не сработало, кроме trap >trap_output_fileкак вывести его в файл (fifo не будет работать bash 3.2.57), а затем прочитать его обратно с помощьюtrap_output="$(<trap_output_file)"

fifo не будет работать, bash 3.2.57потому что trap &пуст для, bash 3.2.57но неbash 4.4.12

GNU bash, версия 4.4.12 (1) -релиз (x86_64-apple-darwin16.3.0):

mkfifo /tmp/fifo; trap >/tmp/fifo & trap_output=$(</tmp/fifo); rm -f /tmp/fifo; echo "$trap_output"
# trap -- 'echo hello' EXIT

mkfifo /tmp/fifo; trap_output=$(</tmp/fifo) & trap >/tmp/fifo; rm -f /tmp/fifo; echo "$trap_output"
# empty because trap_output=$(</tmp/fifo) sets the variable in a subshell

GNU bash, версия 3.2.57 (1) -релиз (x86_64-apple-darwin16):

mkfifo /tmp/fifo; trap >/tmp/fifo & trap_output=$(</tmp/fifo); rm -f /tmp/fifo; echo "$trap_output"
# empty because trap >/tmp/fifo & is empty since it uses trap &

mkfifo /tmp/fifo; trap_output=$(</tmp/fifo) & trap >/tmp/fifo; rm -f /tmp/fifo; echo "$trap_output"
# empty because trap_output=$(</tmp/fifo) sets the variable in a subshell

2

trap определения не распространяются на подоболочки.

Проверить по:

trap "echo bla" 1 2 3"

(trap)


2
Многие оболочки обрабатывают (trap)как особый случай, так что подоболочка может сообщать (но не использовать) ловушки родительской оболочки. Так что этот тест не всегда надежен.
JigglyNaga

Он работает с Bourne Shell , и это дериваты: ksh88, bosh(Шили Bourne Shell) и heirloom-sh. Вы правы: ksh93ведет себя по-разному.
Шили

Это не работает в bash, который использует рассматриваемый скрипт.
JigglyNaga

Ну, это работает в Bash: bashничего не выводит, если вы звоните (trap).
Шили
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.