Bash 如何在使用';set-e';在狂欢节上
我有一个简单的脚本:Bash 如何在使用';set-e';在狂欢节上,bash,interrupt-handling,Bash,Interrupt Handling,我有一个简单的脚本: #!/bin/bash set -e trap "echo BOO!" ERR function func(){ ls /root/ } func 如果我的脚本失败,我想捕获ERR(因为在这里b/c我没有查看/root的权限)。但是,当使用set-e时,它不会被捕获。如果没有set-eERR被捕获 根据bash手册页,对于set-e: 。。。如果设置了ERR,则在shell退出之前执行trap on ERR 为什么我的陷阱没有被执行?从手册页上看,它似乎应该
#!/bin/bash
set -e
trap "echo BOO!" ERR
function func(){
ls /root/
}
func
如果我的脚本失败,我想捕获ERR(因为在这里b/c我没有查看/root的权限)。但是,当使用set-e
时,它不会被捕获。如果没有set-e
ERR被捕获
根据bash手册页,对于set-e
:
。。。如果设置了ERR,则在shell退出之前执行trap on ERR
为什么我的陷阱没有被执行?从手册页上看,它似乎应该这样做。将
错误
替换为退出
,它就会工作
trap
命令的语法是:trap[COMMANDS][SIGNALS]
有关更多信息,请阅读是最好的解决方案:如果希望将set-e
(与:set-o errexit
相同)与ERR
陷阱相结合,也可以使用set-o errtrace
(与:set-e
相同)
简而言之:使用set-eE
代替set-e
:
#!/bin/bash
set -eE # same as: `set -o errexit -o errtrace`
trap 'echo BOO!' ERR
function func(){
ls /root/
}
# Thanks to -E / -o errtrace, this still triggers the trap,
# even though the failure occurs *inside the function*.
func
一个更复杂的示例trap
以红色打印消息并同时打印退出代码的示例:trap'printf”\e[310m%s:%s\e[m\n“BOO!”$?“ERR
manbash
谈到set-o errtrace
/set-E
:
如果设置了ERR,则shell函数、命令替换和在子shell环境中执行的命令将继承ERR上的任何陷阱。在这种情况下,ERR陷阱通常不会继承
我认为正在发生的事情:
- 无
:函数中的-e
命令失败,并且由于是函数中的最后一个命令,函数将ls
的非零退出代码报告给调用者,即顶级脚本作用域。在该作用域中,ls
陷阱生效,并被调用(但请注意,除非从陷阱中显式调用ERR
,否则执行将继续)exit
- 使用
(但不使用-e
):函数内部的-e
命令失败,并且由于ls
有效,Bash立即直接从函数作用域退出,并且由于没有有效的set-e
陷阱(因为它不是从父作用域继承的),您的陷阱未被调用ERR
虽然
man
页面没有错误,但我同意这种行为并不明显-你必须推断出来。你需要使用set-o errtrace
函数来继承陷阱。虽然这是一种可行的解决方法(尽管不需要,如果使用了set-o errtrace
),您应该提到,如果成功终止,也会调用EXIT
,因此您需要添加一个条件,例如if[[$?-ne 0]]…
到处理程序。顺便说一句:最好是单引号引用陷阱处理程序,除非您明确希望它中的变量引用提前展开。如果您使用shopt-s extdebug
,则不必这样做。谢谢,我会这样做。当我运行bash try.sh
时,也不用使用ls/root/
,因为它有#!/bin/bash exit 1
>,它不会被陷阱捕获,如果被调用的脚本退出,有没有办法捕获它?@alper当脚本退出时,无论出于何种原因,无论是否成功,都会调用一个单独的退出
陷阱。要仅对非零退出代码执行操作,必须选中$?
;例如:陷阱'ec=$?;((ec!=0))&&echo“因故障退出:$ec”'退出