Bash陷阱未在最后一个cmd上执行-c传递的脚本


2

这是一个例子:

$ (newline=$'\n'; bash -c "trap 'trap ERR; echo handler' ERR; set -e;${newline}/bin/false")

如果执行以下任一操作,该处理程序将执行:

  • 删除换行符
  • 代替退出
  • 最后添加另一个命令

我怀疑bash有一个优化,如果只有一个命令,则仅调用exec,而换行符后接一个命令即可触发它。

我有间接证据:我遇到了麻烦;较早的cmds将先执行vfork然后执行,但是最后一个仅调用execv。

我遇到了使用.ONESHELL和陷阱打印退出代码和日志文件名的GNU make的问题,但是如果最后一件失败了,陷阱将不会执行。

提前致谢。


您的示例在Debian GNU / Linux 9的GNU Bash 4.4.12(1)
。– Kamil Maciorowski

感谢您提醒我有关此问题的信息;我已经添加了答案。
布莱恩·范登堡

Answers:


1

我忘记了这个问题。我在2016年为bash贡献了一个修复程序:

                   4/22
                   ----
builtins/evalstring.c
    - should_suppress_fork: don't suppress the fork if there are any traps
      set, since that requires that we hang around to react to a signal or
      collect the command's exit status and run something.  Fixes bug
      reported by Brian Vandenberg

正如我在我的问题中所推测的那样,bash确实具有优化功能。自从我看过代码以来已经有一段时间了,但是它或多或少地做到了以下几点:

  1. 解析直到确定完整的表达式,然后对其求值,然后解释或执行求值后剩余的内容
  2. 重复(1),直到只剩下一个表达式
  3. 如果最后一个表达式不需要shell的帮助,并且可以传递给exec()Family函数,则可以这样做

我的解决方法是通过检查是否有任何陷阱来添加“不需要外壳程序提供任何帮助”的定义。

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.