bash shell(rh linux平台,bash 3.2),以后基本上默认是这个平台,不再强调了呵。
今天有个写java的群友问了个shell问题(看看写java的人起的函数名,都这么java,呵呵)
为什么 rm文件不存在,没有调起trap
trap 'echo 抓住非零返回值' ERR
function preparePvmsDailyData { local PVMSDATADIR="/apps/pvmsnas/temp" rm "${PVMSDATADIR}"/*JRN* echo helloword }
trap以前虽然是用过的,但他这问题一时还回答不上来,然后就查起文档,现学现卖了起来
首先还是查man trap,看看啥情况会调起
trap [-lp] [[arg] sigspec ...]
The command arg is to be read and executed when the shell receives signal(s) sigspec.
If a sigspec is ERR, the command arg is executed
whenever a simple command has a non-zero exit status, subject to the following conditions. The ERR trap
is not executed if the failed command is part of the command list immediately following a while or until
keyword, part of the test in an if statement, part of a && or || list, or if the command's return value
is being inverted via !.
也就是说,排除排除在while,until,反的特殊使用情况,对于tra ERR下,命令一旦出错便会报错。
既然如此,为什么没有报错?是不是信号丢了?
简单写了个脚本:
trap 'echo 抓住非零返回值' ERR sub() { ls dfqwefi rm fwjepf } sub
然后执行,发现只报了一个trap
开始怀疑跟跟函数调用有没有关系?是不是没有报错
于是在ls命令与rm命令中sleep了一秒中。
发现结果还是一样,只报了一个trap?
是函数只接收一个信号,还是多个信号覆盖丢了?
继续翻info 文档,info 文档操作来不熟,慢慢的/trap+enter
结果先找到了一个set 参数-E
-E If set, any trap on ERR is inherited by shell functions,
command substitutions, and commands executed in a sub-
shell environment. The ERR trap is normally not inher-
ited in such cases.
原因在于:
这样就明白了,bash默认的关闭了 函数执行体的trap,即不跟进(英文单词叫: inherited )函数内部,
所以我上边的例子,之所以只报一个错,是因为脚本调用了一次sub函数,并返回(通过函数最后一个命令)了非零值。
回头看看java兄的程序,之所以rm不起效果,也是没理解好trap ERR的机制,解决方法可以有这几种:
1:去掉echo helloword
2:在rm下保存存$?,再echo helloword里把保存值return
保存$? : re=$?
return : return $re
3:把trap 写进你的函数里:
4:在脚本最开始处加一个: set -E
其中3,4二种方法让trap跟进了函数。
另外set的一个参数 -e,则是出错即退出,可以做一个有趣的实验
在用户的 ~/.bash_profile里加入下边这二句:
trap '你命令出错了,我要退出了' ERR
set -e
一出错,即shell退出。
呵呵
开个小玩笑
事实上这些选项是可以用在程序调试上边的
比如set -u,一旦脚本中变量未定义,但报错退出
说到shell调试推荐一个网页:
shell调试技术: <http://hi.baidu.com/dabo12/blog/item/b0b799359e405a8da71e122e.html>