A armadilha é herdada por um subshell?

10

Eu tentei um script a seguir:

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

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

A saída do script acima foi:

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

No entanto, eu esperava que o trap fosse chamado também na saída de foo1 , que é chamado em um subshell.

  • Isso é esperado?
  • O trap é herdado por um subshell?
  • Se sim, então, em qual caso trap é herdado por uma subshell?
por Bhagyesh Dudhediya 12.05.2016 / 12:28

3 respostas

7

Os manipuladores de traps nunca são herdados por subshells. Isso é especificado por POSIX :

When a subshell is entered, traps that are not being ignored are set to the default actions.

Note que os sinais ignorados ( trap '' SIGFOO ) permanecem ignorados no subshell (e nos programas externos lançados pelo shell também).

    
por 13.05.2016 / 01:35
4

trap não é propagado para subshells, mas algumas maneiras permitem que o subshell relate as armadilhas do shell pai e outras não. Eu fiz alguns testes em macos com bash.

GNU bash, versão 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, versão 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

É bom saber que trap_output="$(trap)" funcionará para capturar a saída da interceptação. Não consigo pensar em nenhuma outra maneira de fazê-lo, se isso não funcionasse, além de fazer trap >trap_output_file para enviá-lo para um arquivo (fifo não funcionará em bash 3.2.57 ) e, em seguida, lê-lo novamente com trap_output="$(<trap_output_file)"

O fifo não funciona em bash 3.2.57 porque trap & está vazio para bash 3.2.57 , mas não bash 4.4.12

GNU bash, versão 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, versão 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
    
por 29.06.2017 / 21:43
2

trap definições não são propagadas para sub-shells.

Verifique por:

trap "echo bla" 1 2 3"

(trap)

    
por 12.05.2016 / 12:38