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?

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


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

2

trap definisi tidak disebarkan ke sub-shell.

Verifikasi oleh:

trap "echo bla" 1 2 3"

(trap)


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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.