¿La trampa es heredada por una subshell?


14

Intenté un siguiente script:

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

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

El resultado para el script anterior fue:

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

Sin embargo, esperaba que también se llamara a trap en la salida foo1, que se llama en una subshell.

  • ¿Se espera esto?
  • ¿Es trapheredado por una subshell?
  • En caso afirmativo, ¿en qué caso lo traphereda una subshell?

Respuestas:


10

Los manipuladores de trampas nunca son heredados por subcapas. Esto lo especifica POSIX :

Cuando se ingresa un subshell, las trampas que no se ignoran se establecen en las acciones predeterminadas.

Tenga en cuenta que las señales ignoradas ( trap '' SIGFOO) permanecen ignoradas en el subshell (y también en los programas externos lanzados por el shell).


3
En bash puedes set -Epara que las subcapas hereden las trampas, pero es REALMENTE difícil hacerlo bien (al menos en mi experiencia).
— dragon788

No sé si esto funciona para todas las trampas. Sé que funciona para ERR
— yosefrow

4

trapno se propaga a subcapas, pero algunas formas permiten que la subcadena informe las trampas de la capa principal y otras no. Hice algunas pruebas en macos con bash.

GNU bash, versión 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, versión 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

Es bueno saber que trap_output="$(trap)"funcionará para capturar la captura de salida. No puedo pensar en otra forma de hacerlo si eso no funcionó, además trap >trap_output_filede enviarlo a un archivo (no funcionará en Fifo bash 3.2.57) y luego volver a leerlo contrap_output="$(<trap_output_file)"

Fifo no funcionará bash 3.2.57porque trap &está vacío bash 3.2.57pero nobash 4.4.12

GNU bash, versión 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, versión 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 las definiciones no se propagan a subcapas.

Verificar por:

trap "echo bla" 1 2 3"

(trap)


2
Muchos shells se manejan (trap)como un caso especial, de modo que el subshell puede informar (pero no usar) las trampas del shell principal. Entonces esa prueba no siempre es confiable.
— JigglyNaga

Funciona con la shell Bourne y su derivados: ksh88, bosh(schily Bourne Shell) y heirloom-sh. Tienes razón: se ksh93comporta de manera diferente.
— schily

No funciona en bash, que utiliza el script en cuestión.
— JigglyNaga

Bueno, funciona en bash: bashno genera nada si llamas (trap).
— schily
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.