假设您有一个 shell 脚本,它通过EXIT陷阱运行某种清理代码,如下所示:
#!/bin/bash
mytrap () {
echo "It's a trap!" >&2
}
trap mytrap exit
echo I am at the end of the script.
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,这将It's a trap!在脚本退出时打印出来:
$ sh myscript
I am at the end of the script.
It's a trap!
Run Code Online (Sandbox Code Playgroud)
您修改脚本以添加一个函数,该函数生成一些最终通过管道传输到另一个命令的输出,如下所示:
#!/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.
Run Code Online (Sandbox Code Playgroud)
由于管道,代码在myfunc子shell中运行......并且子shell似乎没有继承trap父级的行为,这意味着如果您在这里执行任何应该由您的陷阱代码清除的操作,不会发生。
所以你试试这个:
myfunc () {
trap mytrap EXIT
echo "I've got a bad feeling about this..."
}
Run Code Online (Sandbox Code Playgroud)
并且mytrap在子shell退出时仍然无法触发。事实证明,您需要一个明确的exit,如下所示:
myfunc () {
trap mytrap EXIT
echo "I've got a bad feeling about this..."
exit
}
Run Code Online (Sandbox Code Playgroud)
使用上面的代码,mytrap将在退出子shell时适当触发:
$ sh myscript
It's a trap!
I am at the end of the script.
It's a trap!
Run Code Online (Sandbox Code Playgroud)
这是预期的行为吗?我对这里的几件事感到惊讶:
trap 设置没有被子shell继承EXIT
陷阱bashtrap内置允许关键字RETURN. 因此改变:
trap mytrap EXIT
Run Code Online (Sandbox Code Playgroud)
到:
trap mytrap RETURN
Run Code Online (Sandbox Code Playgroud)
见的讨论trap中壳内建