我有一个相当复杂的bash脚本层次结构,几乎所有东西都依赖于函数。主脚本只是一个shell,它包含在他们自己的文件中包含的适当函数(常见的函数,如我的输出函数等,以及正在执行的任务的特定函数)。
在该框架内,我有一个特殊的功能,需要正确处理中断和清理。我正在处理它在该函数中的子函数中的错误清理 即。
function my_function {
function f_err_cleanup {
do error cleanup tasks here
} #/f_err_cleanup{}
echo do stuff
my_other_function -t "some var here"
my_other_other_function var1 var2 var3
echo do more stuff
} #/my_function{}
在主脚本中添加陷阱,如下所示:
trap "declare -p FUNCNAME ; f_err_cleanup" INT QUIT TERM
由于不知道f_err_cleanup {}函数而失败 - 但陷阱触发。
^C./my_script.sh: line 1: declare: FUNCNAME: not found ./my_script.sh: line 1: f_err_cleanup: command not found [ ERROR 13 ] Script "my_script.sh" failed.
在my_function {}中放置一个陷阱永远不会触发,而cntl-c只是通过130退出代码退出该函数(主脚本随后会处理。
trap "echo inside trap ; declare -p FUNCNAME" EXIT SIGHUP SIGQUIT SIGINT SIGTERM
以上代码段在执行时失败如下
^C[ ERROR 13 ] Script "my_script.sh" failed.
这是来自外部脚本的剪辑:
. my_function
my_function "$@" 2>&1 | tee -a "${RUNTIME_LOG}"
declare -i RC=${PIPESTATUS[0]}
if [[ ${RC} -ne 0 ]]; then
f_err -f -c ${RC} -m "script \"${ME}\"failed\n"
else
f_out "success\n"
exit ${RC}
fi
f_err是一个打印错误消息并使用提供的代码退出的函数。 如何从函数中获取陷阱?
P.S。让外部陷阱执行declare -p FUNCNAME
返回FUNCNAME也是未知,即使我理解它应该显示FUNCNAME[0]="main"
答案 0 :(得分:1)
在my_function {}中设置陷阱永远不会触发
是的。您只是无法分辨,因为您使用echo
写入stdout,而stdout是一个损坏的管道,因为tee
被您尝试处理的sigint杀死。
这是一个MCVE:
#!/bin/bash
myfunction() (
trap 'mycleanup' INT
mycleanup() {
# Write to stderr so we can see it
echo "Cleaning up" >&2
}
echo "doing stuff"
sleep 42
echo "done with stuff"
)
myfunction | tee file
(函数的显式子shell不是绝对必要的,但有助于防止意外地破坏脚本自己的陷阱)
以下是运行和中断时发生的情况:
$ ./myscript
doing stuff
^CCleaning up
答案 1 :(得分:0)
作为答案发布,因为虽然我没有解决在管道中定义的陷阱工作的难题,但我已经解决了我的问题。
因为在这种情况下我的管道只是调用tee
来启用日志记录,所以我能够将管道线路更改为
my_function "$@" &> >( tee -a "${RUNTIME_LOG}" )
由于不再涉及管道,现在将触发函数中的陷阱,而不考虑bash错误处理的可疑性质。