Le piège est-il hérité d'un sous-shell?

14

J'ai essayé un script suivant:

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

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

La sortie du script ci-dessus était:

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

Cependant, je m'attendais à ce que le piège soit appelé à la sortie de foo1, ce qui est appelé dans un sous-shell.

  • Est-ce attendu?
  • Est traphérité par un sous-shell?
  • Si oui, dans quel cas est traphérité d'un sous-shell?
Bhagyesh Dudhediya
la source

Réponses:

10

Les gestionnaires de pièges ne sont jamais hérités par les sous-coquilles. Ceci est spécifié par POSIX :

Lorsqu'un sous-shell est entré, les interruptions qui ne sont pas ignorées sont définies sur les actions par défaut.

Notez que les signaux ignorés ( trap '' SIGFOO) restent ignorés dans le sous-shell (et dans les programmes externes lancés par le shell également).

Gilles 'SO- arrête d'être méchant'
la source
3
En bash, vous pouvez set -Epour que les sous-coquilles héritent des pièges, mais il est VRAIMENT difficile de bien faire les choses (du moins d'après mon expérience).
dragon788
Je ne sais pas si cela fonctionne pour tous les pièges. Je sais que cela fonctionne pour ERR
yosefrow
4

trapn'est pas propagé aux sous-coquilles mais certaines manières permettent à la sous-coquille de signaler les pièges du shell parent et d'autres pas. J'ai fait quelques tests sur macos avec bash.

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

Il est bon de savoir que trap_output="$(trap)"cela fonctionnera pour capturer la sortie du piège. Je ne peux pas penser à une autre façon de le faire si cela n'a pas fonctionné à part le faire trap >trap_output_filepour le sortir dans un fichier (fifo ne fonctionnera pas bash 3.2.57) et le relire ensuite avectrap_output="$(<trap_output_file)"

fifo ne fonctionnera pas bash 3.2.57parce qu'il trap &est vide bash 3.2.57mais pasbash 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
la source
2

trap les définitions ne sont pas propagées aux sous-coques.

Vérifiez par:

trap "echo bla" 1 2 3"

(trap)

schily
la source
2
De nombreux shells sont traités (trap)comme un cas spécial, de sorte que le sous-shell peut signaler (mais pas réellement utiliser) les pièges du shell parent. Ce test n'est donc pas toujours fiable.
JigglyNaga
Il fonctionne avec le Bourne Shell et est: dérivés ksh88, bosh(schily Bourne Shell) et heirloom-sh. Vous avez raison: ksh93se comporte différemment.
schily
Cela ne fonctionne pas en bash, que le script en question utilise.
JigglyNaga
Eh bien, cela fonctionne en bash: bashne produit rien si vous appelez (trap).
schily