群里有位朋友反映维护的tomcat常常内存溢出,导致应用挂掉,想要写一个脚本定时关闭tomcat并重启tomcat。由于其本身不是做java开发,仅仅是按领导吩咐实现功能,并不打算解决内存溢出的问题,所以使用crontab+shell脚本的方式定时关闭启动就OK了。
为此给出参考脚本
#!/bin/sh
export JAVA_HOME=/home/app/jdk1.8
export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
pid=`ps -ef|grep /home/app/apache-tomcat-8.5.57|grep -v grep|awk '{print $2}'`
echo $pid
/home/app/apache-tomcat-8.5.57/bin/shutdown.sh
sleep 60
num=`ps -ef|grep /home/app/apache-tomcat-8.5.57|grep -v grep|wc -l`
if [ $num -ne 0 ]
then
echo "Tomcat进程仍然存活,强制杀掉进程$pid"
kill -9 $pid
sleep 2
else
echo "Tomcat已正常shutdown"
fi
/home/app/apache-tomcat-8.5.57/bin/startup.sh
思路很简单,先使用tomcat的shutdown脚本尝试关闭tomcat,由于有内存溢出的问题,估计tomcat的关闭会比较不顺利,预留1分钟的时间进行关闭,如果1分钟内还没有正常关闭,则认为tomcat卡死无法正常关闭,使用kill -9杀死进程,再执行startup启动tomcat
群友使用关键语句进行测试,发现在kill时其他的tomcat的也被关闭了,显然是grep过滤ps命令时出了问题,虽然可以修改grep后的关键词来准确定位tomcat,但是复杂性增加,所以建议他使用lsof来获取pid,因为端口不会重复占用
#!/bin/sh
export JAVA_HOME=/home/app/jdk1.8
export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
pid=`lsof -i:8080|grep -v PID|awk '{print $2}'`
echo $pid
/home/app/apache-tomcat-8.5.57/bin/shutdown.sh
sleep 60
num=`lsof -i:8080|grep -v PID|wc -l`
if [ $num -ne 0 ]
then
echo "Tomcat进程仍然存活,强制杀掉进程$pid"
kill -9 $pid
sleep 2
else
echo "Tomcat已正常shutdown"
fi
/home/app/apache-tomcat-8.5.57/bin/startup.sh
群友测试过后表示可以正常重启,但是由于shutdown总是关不掉tomcat,他没有使用shutdown,直接就kill了。
对于此类问题,还是得从代码处着手。存在内存溢出,很可能有内存泄漏,或者是业务量需要扩容,增加服务器来构建负载。还是常规使用jstack,jstat等工具进行问题分析后找到问题解决问题,否则最后业务中断的锅很可能还是要运维来背。