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?

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).


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

2

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

Vérifiez par:

trap "echo bla" 1 2 3"

(trap)


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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.