La trap è ereditata da una subshell?


14

Ho provato un seguente script:

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

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

L'output per lo script sopra era:

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

Tuttavia mi aspettavo che anche la trap venisse chiamata all'uscita foo1, che viene chiamata in una subshell.

  • È previsto?
  • È trapereditato da una subshell?
  • Se sì, allora in che caso viene trapereditato da una subshell?

Risposte:


10

I gestori di trap non vengono mai ereditati dai subshells. Questo è specificato da POSIX :

Quando viene immessa una subshell, le trap che non vengono ignorate vengono impostate sulle azioni predefinite.

Si noti che i segnali ignorati ( trap '' SIGFOO) rimangono ignorati nella subshell (e anche nei programmi esterni lanciati dalla shell).


3
In bash puoi fare set -Ein modo che le subshells ereditino le trappole, ma è DAVVERO complicato ottenere il giusto (almeno nella mia esperienza).
dragon788,

Non so se questo funziona per tutte le trappole. So che funziona per ERR
yosefrow

4

trapnon è propagandato alle subshell ma alcuni modi consentono alla subshell di segnalare le trap della shell padre e altre no. Ho fatto alcuni test su macos con bash.

GNU bash, versione 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, versione 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

È bene sapere che trap_output="$(trap)"funzionerà per catturare l'output trap. Non riesco a pensare a nessun altro modo di farlo se non funzionasse oltre a fare trap >trap_output_filel'output su un file (il file FIFO non funzionerà bash 3.2.57) e poi rileggerlo contrap_output="$(<trap_output_file)"

FIFO non funzionerà bash 3.2.57perché trap &è vuoto per bash 3.2.57ma nonbash 4.4.12

GNU bash, versione 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, versione 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 le definizioni non vengono propagate alle sotto shell.

Verifica tramite:

trap "echo bla" 1 2 3"

(trap)


2
Molte shell vengono gestite (trap)come un caso speciale, in modo che la subshell possa segnalare (ma non effettivamente utilizzare) le trap della shell padre. Quindi quel test non è sempre affidabile.
JigglyNaga,

Funziona con la Bourne Shell ed è derivati: ksh88, bosh(Schily Bourne Shell) e heirloom-sh. Hai ragione: ksh93si comporta diversamente.
schily,

Non funziona in bash, che utilizza lo script in questione.
JigglyNaga,

Bene, funziona in bash: bashnon emette nulla se chiami (trap).
schily,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.