如何在 Zsh 中无条件地捕获 EXIT(即使被中断)?

如何在 Zsh 中无条件地捕获 EXIT(即使被中断)?

我想捕获函数的退出钩子。 Bash 提供了一个很好的信号,称为RETURN(非 POSIX),当函数返回时会调用该信号,例如

function test_trap() {
    trap 'echo trapped' RETURN
    sleep 10  # simulate time-consuming commands
    echo done
}

当函数返回时我看到“被困”,即使我发送SIGINT一个Ctrl C。 Zsh 有类似的功能吗?我EXIT在 Zsh 中尝试过,但它只捕获正常返回,而不是当我用 中断时SIGINT。我也尝试过诱捕两个都 EXITINT具有相同的钩子函数,但它有两个问题:

  1. 当我中断它时,钩子表达式会被计算两次。没什么大不了;我的钩子表达式恰好是幂等的。
  2. Zsh 中的EXIT是本地的:从函数返回时,恢复原来的钩子。这类似于局部变量隐藏全局变量的方式。不幸的是,该INT钩子始终是全局的,因此我指定的任何钩子都会覆盖全局钩子。我需要记住原来的INT钩子,并在以后恢复它。正确地做到这一点非常棘手;我可能会尝试一下这个。

答案1

这就像函数外部的 EXIT 陷阱一样。退出和被杀是两件事。

因此,就像在函数之外一样,您需要单独处理它们:

test_trap() {
  set -o localoptions -o localtraps
  trap 'echo "I am exiting."' EXIT
  trap 'echo "I have been interrupted, so"; return 1' INT

  echo start
  sleep 10
  echo end
}

test_trap
echo "returned with: $?"

这使:

$ zsh ./that-script
start
^CI have been interrupted, so
I am exiting.
returned with: 1

如果你想要(不仅仅是函数)在执行函数时收到处理 SIGINT 信号时退出,替换return 1exit(或者在恢复默认处理程序(trap - INT; kill -s INT "$$")后用 SIGINT 杀死自己,如果你想通过信号向你的父母报告你的死亡) 。

相关内容