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?

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.


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

2

trap Definitionen werden nicht an Unterschalen weitergegeben.

Überprüfen durch:

trap "echo bla" 1 2 3"

(trap)


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.