Wird die Falle von einer Unterschale geerbt?

14

Ich habe folgendes Skript ausprobiert:

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

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

Die Ausgabe für das obige Skript war:

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

Ich hatte jedoch damit foo1gerechnet, dass die Falle auch beim Verlassen aufgerufen wird , was in einer Unterschale heißt.

  • Wird das erwartet?
  • Wird trapvon einer Unterschale geerbt?
  • Wenn ja, in welchem ​​Fall wird trapeine Unterschale vererbt?
Bhagyesh Dudhediya
quelle

Antworten:

10

Trap-Handler werden niemals von Subshells geerbt. Dies wird von POSIX festgelegt :

Wenn eine Subshell eingegeben wird, werden Traps, die nicht ignoriert werden, auf die Standardaktionen gesetzt.

Beachten Sie, dass ignorierte Signale ( trap '' SIGFOO) in der Subshell (und auch in externen Programmen, die von der Shell gestartet werden) ignoriert werden.

Gilles 'SO - hör auf böse zu sein'
quelle
3
In bash kann man set -E, um Subshells zu haben, Traps erben, aber es ist WIRKLICH schwierig, es richtig zu machen (zumindest nach meiner Erfahrung).
Dragon788
Ich weiß nicht, ob das für alle Fallen funktioniert. Ich weiß, es funktioniert für ERR
Yosefrow
4

trapwird nicht auf Subshells übertragen, aber einige Methoden ermöglichen es der Subshell, die Überfüllungen der übergeordneten Shell zu melden, andere nicht. Ich habe einige Tests auf Macos mit Bash gemacht.

GNU Bash, Version 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, Version 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

Das ist gut zu wissen, dass trap_output="$(trap)"es funktioniert, um die Trap-Ausgabe zu erfassen. Ich kann mir keine andere Möglichkeit trap >trap_output_filevorstellen, das zu tun , als es in eine Datei auszugeben (in der FIFO nicht funktioniert bash 3.2.57) und es dann wieder einzulesentrap_output="$(<trap_output_file)"

fifo funktioniert nicht, bash 3.2.57weil trap &es leer ist, bash 3.2.57aber nichtbash 4.4.12

GNU Bash, Version 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, Version 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
quelle
2

trap Definitionen werden nicht an Unterschalen weitergegeben.

Überprüfen durch:

trap "echo bla" 1 2 3"

(trap)

schily
quelle
2
Viele Shells werden (trap)als Sonderfall behandelt, sodass die Subshell die Überfüllungen der übergeordneten Shell melden (aber nicht verwenden) kann. Dieser Test ist also nicht immer zuverlässig.
JigglyNaga
Es arbeitet mit der Bourne - Shell und es ist Derivaten: ksh88, bosh(schily Bourne Shell) und heirloom-sh. Sie haben recht: ksh93verhält sich anders.
Schily
Es funktioniert nicht in Bash, die das betreffende Skript verwendet.
JigglyNaga
Nun, es funktioniert in Bash: bashGibt nichts aus, wenn Sie anrufen (trap).
schily