外壳程序脚本中的陷阱处理和隐式子外壳


12

假设您有一个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子外壳中运行...并且子外壳似乎没有继承trap父对象的行为,这意味着如果您在此处执行任何应由陷阱代码清除的操作,则不会不会发生。

所以你试试这个:

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 陷阱

Answers:


8

bash trap内置的允许关键字RETURN。因此更改:

trap mytrap EXIT

至:

trap mytrap RETURN

见的讨论trap壳内建

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.