一个看似奇怪的Shell脚本问题

Posted 杨建荣的学习笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个看似奇怪的Shell脚本问题相关的知识,希望对你有一定的参考价值。

这是学习笔记的第 1855篇文章


登录到服务器之后,发现tomcat竟然停了。查看上下文的环境都没有看到相关的日志,排除了人为操作的因素之后,初步判断是开源调度后端的一种异常处理机制。 这个调度任务的部署是基于agent的方式,服务端会不断的去扫描agent端的心跳,目前是按照5秒的节奏。

所以为了尽快修复问题,就果断使用了问题修复三板斧的重启大法,重启之后,服务很快正常了。业务同学就把这个事情淡忘了。

但是这个问题在我脑海里还是存在疑问,因为最近已经出了两次类似的情况了。

如果再次碰到这个问题,我们是否能够很快定位到问题,及时修复问题。在这个问题的处理上,在日志有限的情况下,我决定先采用另外一种更主动的方式来临时解决,也就是不断的探测tomcat服务,如果服务不可用,则重启tomcat服务,依次轮询。

大概用了不到5分钟,就写了一个初步的demo版本。

基本思路就是通过tomcat去检查相关的进程,如果不存在tomcat进程,则得到0,会重启服务,否则存在tomcat服务,得到的值为1,则只是输出正常的轮询信息,脚本名为check_tomcat.sh

。。。

tomcat_process_alive=`ps -ef|grep tomcat|grep -v grep|wc -l  `

echo $tomcat_process_alive


if [[ $tomcat_process_alive -eq 1 ]];then

 echo 'tomcat process is dead....'

 sh  /usr/local/tomcat/bin/startup.sh 

 echo "restart tomcat ... " `date` >> /tmp/tomcat_check.log

else

 echo 'tomcat process is OK...'

 echo " tomcat is OK ... " `date` >> /tmp/tomcat_check.log

fi


在边写边测试,感觉逻辑已经足够简单了,实在没有什么出差错的可能性了,于是叫业务同学来做下测试,看看这个服务能不能正常探测启动服务。

但是让我汗颜的是,这样一个看起来很简单的脚本,竟然没有执行不符合预期,在tomcat进程存在的前提下,得到的tomcat进程数是3而不是1,这个让我大跌眼镜。

我们初期是根据ps -ef|grep tomcat来得到相关的进程,然后根据进程信息来判断tomcat是否存活,怎么冒出来了其他的几个进程呢。 单独执行命令显示是1,把这个逻辑拷贝到一个临时文件b.sh执行结果也是1,明明正确的,结果显示就是不对。

如果tomcat不存在的时候,进程数显示是2,非常诡异。

对于这类问题,一种方式就是我们小心翼翼的妥协,要不就是直面问题。

一种调试方法就是使用 -x

# sh -x check_tomcat.sh 

++ ps -ef

++ grep tomcat

++ grep -v grep

++ wc -l

+ tomcat_process_alive=3

+ echo 3

3

+ [[ 3 -eq 1 ]]

+ echo 'tomcat process is OK...'

tomcat process is OK...

++ date

+ echo ' tomcat is OK ... ' Thu Jan 10 22:50:03 CST 2019


可以看到脚本里面得到的结果是3,但是要分析问题原因,目前来看信息还是不够,另外一种方法更加直接,既然wc -l显示为3,那么我们就把完整结果输出出来。 

# sh check_tomcat.sh 

root      26196  42250  0 23:38 pts/19   00:00:00 sh check_tomcat.sh

root      26198  26196  0 23:38 pts/19   00:00:00 grep tomcat

root      42831      1  1 21:33 pts/19   00:01:18 /usr/local/jdk1.8.0_152/jre/bin/java-xxxx org.apache.catalina.startup.Bootstrap start

可以看到,这个执行会有一个进程是对应相关的脚本名。即sh check_tomcat.sh字样的进程。

到了这里,问题的原因就很明显了。

修复方式就是我们重新调整下脚本命名,而这个问题在一个相对复杂的场景下去定位,其实会成为一个更加诡异的问题,这里也就能反应出我们对于脚本的逻辑检查还是存在问题,在使用规范上也可以有效的结合起来。 

以上是关于一个看似奇怪的Shell脚本问题的主要内容,如果未能解决你的问题,请参考以下文章

linux shell脚本换行问题

无法从 bash shell 脚本执行 Tcl 脚本

shell脚本中实现自动判断用户有无密码

shell脚本的条件测试的奇怪内容

为啥正确的 shell 脚本会给出包装/截断/损坏的错误消息? [复制]

异步shell命令