Là bẫy được thừa hưởng bởi một subshell?


14

Tôi đã thử một đoạn script sau:

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

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

Đầu ra cho đoạn script trên là:

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

Tuy nhiên, tôi đã mong đợi cái bẫy cũng được gọi khi thoát ra foo1, cái này được gọi trong một subshell.

  • Đây có phải là mong đợi?
  • Được trapthừa hưởng bởi một subshell?
  • Nếu có, thì trong trường hợp nào được trapthừa kế bởi một subshell?

Câu trả lời:


10

Xử lý bẫy không bao giờ được thừa kế bởi subshells. Điều này được chỉ định bởi POSIX :

Khi một lớp con được nhập, các bẫy không bị bỏ qua sẽ được đặt thành các hành động mặc định.

Lưu ý rằng các tín hiệu bị bỏ qua ( trap '' SIGFOO) vẫn bị bỏ qua trong lớp con (và trong các chương trình bên ngoài được khởi chạy bởi shell).


3
Trong bash, bạn có thể có các set -Ebẫy con kế thừa các bẫy, nhưng thật khó để có được quyền (ít nhất là theo kinh nghiệm của tôi).
dragon788

Tôi không biết nếu điều này làm việc cho tất cả các bẫy. Tôi biết nó hoạt động cho ERR
yosefrow

4

trapkhông được hỗ trợ cho các lớp con nhưng một số cách cho phép lớp con báo cáo các bẫy của lớp vỏ mẹ và các cách khác thì không. Tôi đã làm một số thử nghiệm trên macos với bash.

GNU bash, phiên bả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, phiên bả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

Điều này là tốt để biết rằng trap_output="$(trap)"sẽ làm việc để nắm bắt đầu ra bẫy. Tôi không thể nghĩ ra cách nào khác để làm điều đó nếu điều đó không hiệu quả ngoài việc thực hiện trap >trap_output_fileđể xuất nó thành một tệp (fifo sẽ không hoạt động bash 3.2.57) và sau đó đọc lại bằngtrap_output="$(<trap_output_file)"

fifo sẽ không làm việc bash 3.2.57trap &trống rỗng bash 3.2.57nhưng khôngbash 4.4.12

GNU bash, phiên bả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, phiên bả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 định nghĩa không được truyền đến vỏ phụ.

Xác minh bằng:

trap "echo bla" 1 2 3"

(trap)


2
Nhiều shell xử lý (trap)như một trường hợp đặc biệt, để lớp vỏ có thể báo cáo (nhưng không thực sự sử dụng) các bẫy của shell cha. Vì vậy, bài kiểm tra đó không phải lúc nào cũng đáng tin cậy.
JigglyNaga

Nó hoạt động với Bourne Shell và nó bắt nguồn : ksh88, bosh(schily Bourne Shell) và heirloom-sh. Bạn đúng: ksh93cư xử khác.
schily

Nó không hoạt động trong bash, mà kịch bản trong câu hỏi sử dụng.
JigglyNaga

Chà, nó hoạt động trong bash: bashkhông xuất ra bất cứ thứ gì nếu bạn gọi (trap).
schily
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.