这是学习笔记的第 1855篇文章
今天早上同事打电话说有一个任务调度的服务停了。这是一个基于Java的开源项目,web服务器是tomcat,根据反馈是页面访问不了了,所以初步诊断是tomcat服务出现了问题。
登录到服务器之后,发现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字样的进程。
到了这里,问题的原因就很明显了。
修复方式就是我们重新调整下脚本命名,而这个问题在一个相对复杂的场景下去定位,其实会成为一个更加诡异的问题,这里也就能反应出我们对于脚本的逻辑检查还是存在问题,在使用规范上也可以有效的结合起来。