破折号:如何捕获陷阱的输出(不带参数调用)?

Kon*_*eak 5 dash trap

在本节trap中的破折号手册页出现如下提示:

不带任何参数的trap导致它以适合作为 shell 输入的格式信号列表及其相关操作写入标准输出,以实现相同的捕获结果

惊人的!我以为我找到了一种简单的方法来恢复我已经覆盖的以前的信号处理程序,方法是将trap的输出作为命令返回给 shell:

trap "echo 'good'" EXIT

# save signal handlers to $traps
traps="$(trap)"

# override EXIT handler
trap "echo 'bad'" EXIT

# reinstate original handlers
eval "$traps"
Run Code Online (Sandbox Code Playgroud)

期望的输出: good

实际输出: bad

这是完全合乎逻辑的,因为它$traps是空的,这又与联机帮助页一致:

当 shell 分叉出一个子 shell 时,它会将被捕获(但不会被忽略)的信号重置为默认操作。

(命令替换$(trap)分叉出一个子shell,所以trap不知道任何信号处理程序。)


一切似乎都按其应有的方式行事。但是如何利用trap的列表功能呢?

Sté*_*las 4

您可以重定向到临时文件:

file=$(mktemp) || exit
{
  rm -f -- "$file"
  trap
  traps=$(cat)
} > "$file" < "$file"
Run Code Online (Sandbox Code Playgroud)

请注意,在这方面dash'strap不是 POSIX,因为POSIX 确实要求

var=$(trap)
Run Code Online (Sandbox Code Playgroud)

被视为一种特殊情况,其中陷阱不会在子 shell 中重置。

zsh并且mksh也有这个问题。然而zsh,你可以这样做:

trap | IFS= read -rd '' traps
Run Code Online (Sandbox Code Playgroud)