Чи пастка успадковується підзаголовком?


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

Однак я очікував, що пастка буде викликана і при виході з неї 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поводитесь інакше.
schily

Він не працює в bash, який використовує розглянутий сценарій.
JigglyNaga

Ну, це працює в bash: bashнічого не видає, якщо зателефонувати (trap).
schily
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.