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

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наследуется подоболочка?
Бхагеш Дудхедия
источник
Связанный: unix.stackexchange.com/questions/277090/…
PSkocik

Ответы:

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
dosentmatter
источник
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).
Шили