Apakah jebakan diwarisi oleh subkulit?

14

Saya mencoba skrip berikut:

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

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

Output untuk skrip di atas adalah:

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

Namun saya mengharapkan jebakan untuk dipanggil keluar dari foo1juga, yang disebut dalam subkulit.

  • Apakah ini yang diharapkan?
  • Apakah trapdiwarisi oleh subkulit?
  • Jika ya, lalu dalam hal apa trapdiwariskan oleh subkulit?
Bhagyesh Dudhediya
sumber

Jawaban:

10

Penangan perangkap tidak pernah diwarisi oleh subkulit. Ini ditentukan oleh POSIX :

Ketika subkulit dimasukkan, jebakan yang tidak diabaikan diatur ke tindakan default.

Perhatikan bahwa sinyal yang diabaikan ( trap '' SIGFOO) tetap diabaikan dalam subkulit (dan dalam program eksternal yang diluncurkan oleh shell juga).

Gilles 'SANGAT berhenti menjadi jahat'
sumber
3
Dalam bash Anda dapat set -Ememiliki subshells mewarisi jebakan, tetapi benar-benar sulit untuk mendapatkan yang benar (setidaknya dalam pengalaman saya).
dragon788
Saya tidak tahu apakah ini berfungsi untuk semua perangkap. Saya tahu ini bekerja untuk ERR
yosefrow
4

traptidak dipropagasi ke subkulit tetapi beberapa cara memungkinkan subkulit untuk melaporkan perangkap dari shell induk dan yang lainnya tidak. Saya melakukan beberapa tes pada macos dengan bash.

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

Ini bagus untuk diketahui yang trap_output="$(trap)"akan bekerja untuk menangkap keluaran perangkap. Saya tidak bisa memikirkan cara lain untuk melakukannya jika itu tidak berhasil selain melakukan trap >trap_output_fileuntuk output ke file (fifo tidak akan berfungsi bash 3.2.57) dan kemudian membacanya kembali dengantrap_output="$(<trap_output_file)"

fifo tidak akan berfungsi bash 3.2.57karena trap &kosong untuk bash 3.2.57tetapi tidakbash 4.4.12

GNU bash, versi 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 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
sumber
2

trap definisi tidak disebarkan ke sub-shell.

Verifikasi oleh:

trap "echo bla" 1 2 3"

(trap)

schily
sumber
2
Banyak shell menangani (trap)sebagai case khusus, sehingga subshell dapat melaporkan (tetapi tidak benar-benar menggunakan) perangkap dari shell induk. Jadi tes itu tidak selalu dapat diandalkan.
JigglyNaga
Ia bekerja dengan Bourne Shell dan itu turunan: ksh88, bosh(schily Bourne Shell) dan heirloom-sh. Anda benar: ksh93berperilaku berbeda.
schily
Tidak berfungsi di bash, yang digunakan skrip yang dipertanyakan.
JigglyNaga
Yah, itu bekerja di bash: bashtidak menghasilkan apa-apa jika Anda menelepon (trap).
schily