陷阱是由subshel​​l继承的吗?


14

我尝试了以下脚本:

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

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

上面脚本的输出是:

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

但是,我也希望在退出时也要调用trap foo1,这是在子shell中调用的。

  • 这是预期的吗?
  • trap由subshel​​l继承的吗?
  • 如果是,那么trap子外壳程序在什么情况下会继承?

Answers:


10

陷阱处理程序永远不会被子Shell继承。这是由POSIX指定的

输入子shell后,不会忽略的陷阱将设置为默认操作。

请注意,被忽略的信号(trap '' SIGFOO)在子外壳程序中(以及在由外壳程序启动的外部程序中)仍然被忽略。


3
在bash中,您可以set -E使子shell继承陷阱,但是正确无误(至少以我的经验)。
dragon788

我不知道这是否适用于所有陷阱。我知道它适用于ERR
yosefrow

4

trap不是传播到子shell,但是有些方法允许子shell报告父shell的陷阱,而另一些则不。我用bash在macOS上做了一些测试。

GNU bash版本4.4.12(1)-发行版(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版本3.2.57(1)-发行版(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

很高兴知道这trap_output="$(trap)"将捕获陷阱输出。如果无法trap >trap_output_file将其输出到文件(fifo无法在中工作bash 3.2.57)然后再读回,那么我想不出其他任何方法来做到这一点trap_output="$(<trap_output_file)"

fifo将无法使用,bash 3.2.57因为它trap &为空bash 3.2.57但不是bash 4.4.12

GNU bash版本4.4.12(1)-发行版(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版本3.2.57(1)-发行版(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 定义不会传播到子外壳。

验证方式:

trap "echo bla" 1 2 3"

(trap)


2
许多外壳程序(trap)是一种特殊情况,因此子外壳程序可以报告(但不能实际使用)父外壳程序的陷阱。因此该测试并不总是可靠的。
JigglyNaga

它可以与Bourne Shell一起使用,并且是它的派生:ksh88bosh(schily Bourne Shell)和heirloom-sh。您是正确的:ksh93行为有所不同。
2016年

在有问题的脚本使用的bash中,它不起作用。
JigglyNaga

好吧,它可以在bash中工作:bash如果调用,则不会输出任何内容(trap)
2016年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.