shell 脚本中的陷阱处理和隐式子 shell

shell 脚本中的陷阱处理和隐式子 shell

假设您有一个 shell 脚本,它通过EXIT陷阱运行某种清理代码,如下所示:

#!/bin/bash

mytrap () {
  echo "It's a trap!" >&2
}

trap mytrap exit

echo I am at the end of the script.

正如预期的,这将It's a trap!在脚本退出时打印出来:

$ sh myscript
I am at the end of the script.
It's a trap!

您修改脚本以添加一个函数,该函数生成一些输出,最终通过管道传输到另一个命令,如下所示:

#!/bin/bash

mytrap () {
  echo "It's a trap!" >&2
}

myfunc () {
  echo "I've got a bad feeling about this..."
}

trap mytrap exit

myfunc | cat > /dev/null

echo I am at the end of the script.

由于管道的原因,其中的代码myfunc在子 shell 中运行...并且子 shell 似乎不会继承trap父 shell 的行为,这意味着如果您在此处执行任何应该由陷阱代码清除的操作,则不会'不会发生。

所以你尝试这样做:

myfunc () {
  trap mytrap EXIT
  echo "I've got a bad feeling about this..."
}

mytrap并且当子shell退出时仍然无法触发。事实证明,您需要一个显式的exit,如下所示:

myfunc () {
  trap mytrap EXIT
  echo "I've got a bad feeling about this..."
  exit
}

使用上面的代码,mytrap将在退出子 shell 时适当触发:

$ sh myscript 
It's a trap!
I am at the end of the script.
It's a trap!

这是预期的行为吗?我对这里的几件事感到惊讶:

  • trap设置不被子 shell 继承
  • 从子 shell 隐式退出似乎不会触发EXIT 陷阱

答案1

bashtrap内置允许使用关键字RETURN.因此改变:

trap mytrap EXIT

到:

trap mytrap RETURN

参见trapshell 内置函数

相关内容