Czy pułapka jest dziedziczona przez podpowłokę?

14

Próbowałem następującego skryptu:

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

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

Dane wyjściowe powyższego skryptu były następujące:

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

Jednak spodziewałem się, że pułapka zostanie również wywołana przy wyjściu z foo1, która jest wywoływana w podpowłoce.

  • Czy jest to oczekiwane?
  • Czy trapdziedziczy się podpowłoka?
  • Jeśli tak, to w jakim przypadku trapdziedziczy podpowłoka?
Bhagyesh Dudhediya
źródło

Odpowiedzi:

10

Procedury obsługi pułapek nigdy nie są dziedziczone przez podpowłoki. Jest to określone przez POSIX :

Po wprowadzeniu podpowłoki pułapki, które nie są ignorowane, są ustawiane na akcje domyślne.

Zauważ, że ignorowane sygnały ( trap '' SIGFOO) pozostają ignorowane w podpowłoce (oraz w programach zewnętrznych uruchamianych również przez powłokę).

Gilles „SO- przestań być zły”
źródło
3
W bash możesz set -E, aby podpowłoki dziedziczyły pułapki, ale NAPRAWDĘ trudno jest to naprawić (przynajmniej z mojego doświadczenia).
dragon788
Nie wiem, czy to działa dla wszystkich pułapek. Wiem, że to działa na ERR
yosefrow
4

trapnie jest proponowany do podpowłoki, ale niektóre sposoby umożliwiają podpowłoce zgłaszanie pułapek powłoki nadrzędnej, a inne nie. Zrobiłem kilka testów na macos z bash.

GNU bash, wersja 4.4.12 (1) -release (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, wersja 3.2.57 (1) -release (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

Warto wiedzieć, że trap_output="$(trap)"zadziała, aby przechwycić wyjście pułapki. Nie mogę wymyślić żadnego innego sposobu, aby to zrobić, gdyby to nie zadziałało poza zrobieniem trap >trap_output_filego do pliku (fifo nie zadziała bash 3.2.57), a następnie ponownym odczytaniem go za pomocątrap_output="$(<trap_output_file)"

fifo nie zadziała, bash 3.2.57ponieważ trap &jest pusty, bash 3.2.57ale niebash 4.4.12

GNU bash, wersja 4.4.12 (1) -release (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, wersja 3.2.57 (1) -release (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
źródło
2

trap definicje nie są propagowane do podpowłok.

Weryfikuj przez:

trap "echo bla" 1 2 3"

(trap)

schily
źródło
2
Wiele powłok obsługuje się (trap)jako specjalny przypadek, dzięki czemu podpowłoka może zgłaszać (ale nie używać) pułapek powłoki nadrzędnej. Dlatego ten test nie zawsze jest wiarygodny.
JigglyNaga,
Współpracuje z Bourne Shell i jego pochodne: ksh88, bosh(Schily Bourne shell) i heirloom-sh. Masz rację: ksh93zachowuje się inaczej.
schily,
Nie działa w trybie bash, którego używa dany skrypt.
JigglyNaga,
Cóż, działa w trybie bash: bashnic nie wyświetla, jeśli zadzwonisz (trap).
schily,