子 shell 可见父陷阱但 运行
Parent trap visible but not run by subshell
测试 Bash 5.0.2
Bash performs the expansion [of a command substitution] by executing [the] command in a subshell environment
根据The Open Group Base Specifications Issue 6:
when a subshell is entered, traps that are not being ignored are set to the default actions.
所以当运行使用以下脚本时:
function a {
trap -p EXIT
}
trap "echo 'parent'" EXIT
echo "$(a)"
(a)
trap - EXIT
echo 'exiting'
...我希望输出为:
exiting
...但是我得到:
trap -- 'echo '\''parent'\''' EXIT
trap -- 'echo '\''parent'\''' EXIT
exiting
... 意味着函数 a
- 尽管它在子 shell 中是 运行 - 正在查看父 shell 的陷阱命令(通过 trap -p
)但不执行它们。
这是怎么回事?
您似乎在阅读规范的旧版本。在most recent one,
When a subshell is entered, traps that are not being ignored shall be set to the default actions, except in the case of a command substitution containing only a single trap command, when the traps need not be altered.
您会注意到陷阱完全按照规格触发。只是 trap
的输出出乎意料。
这是 Bash 4.2 (release notes) 中的一个功能:
b. Subshells begun to execute command substitutions or run shell functions or
builtins in subshells do not reset trap strings until a new trap is
specified. This allows $(trap) to display the caller's traps and the
trap strings to persist until a new trap is set.
通常情况下,人们会认为这是理所当然的。考虑一下这个完全不足为奇的 Bash 交换:
bash$ trap
trap -- 'foo' EXIT
trap -- 'bar' SIGINT
bash$ trap | grep EXIT
trap -- 'foo' EXIT
现在看看在 Dash、Ksh 或 Zsh 等其他 shell 中的结果:
dash$ trap
trap -- 'foo' EXIT
trap -- 'bar' INT
dash$ trap | grep EXIT
(no output)
这也许更正确,但我怀疑很多人会期望它。
测试 Bash 5.0.2
Bash performs the expansion [of a command substitution] by executing [the] command in a subshell environment
根据The Open Group Base Specifications Issue 6:
when a subshell is entered, traps that are not being ignored are set to the default actions.
所以当运行使用以下脚本时:
function a {
trap -p EXIT
}
trap "echo 'parent'" EXIT
echo "$(a)"
(a)
trap - EXIT
echo 'exiting'
...我希望输出为:
exiting
...但是我得到:
trap -- 'echo '\''parent'\''' EXIT
trap -- 'echo '\''parent'\''' EXIT
exiting
... 意味着函数 a
- 尽管它在子 shell 中是 运行 - 正在查看父 shell 的陷阱命令(通过 trap -p
)但不执行它们。
这是怎么回事?
您似乎在阅读规范的旧版本。在most recent one,
When a subshell is entered, traps that are not being ignored shall be set to the default actions, except in the case of a command substitution containing only a single trap command, when the traps need not be altered.
您会注意到陷阱完全按照规格触发。只是 trap
的输出出乎意料。
这是 Bash 4.2 (release notes) 中的一个功能:
b. Subshells begun to execute command substitutions or run shell functions or
builtins in subshells do not reset trap strings until a new trap is
specified. This allows $(trap) to display the caller's traps and the
trap strings to persist until a new trap is set.
通常情况下,人们会认为这是理所当然的。考虑一下这个完全不足为奇的 Bash 交换:
bash$ trap
trap -- 'foo' EXIT
trap -- 'bar' SIGINT
bash$ trap | grep EXIT
trap -- 'foo' EXIT
现在看看在 Dash、Ksh 或 Zsh 等其他 shell 中的结果:
dash$ trap
trap -- 'foo' EXIT
trap -- 'bar' INT
dash$ trap | grep EXIT
(no output)
这也许更正确,但我怀疑很多人会期望它。