Linux停止Java服务,与selenium相关问题,部署脚本方案
前言
在部署一些不经过Jenkins的SpringBoot项目时,通常是自己编写nohup的java命令启动。重新部署时,使用JDK 自带的 jps
命令或者 Linux的 ps
(process status) 命令来查出服务进程 ID,然后使用 linux kill -9命令杀死特定的进程。
虽然在一般的教程或文章里,都说直接使用 kill -9 PID
,其实这个是很粗暴的而且极其危险的动作。但由于程序不是关键业务,同时直接杀死在这些项目中也不会造成数据损失,也就没有过多在意。
kill -9问题原因
因为它不管程序现在有没有未处理完的事情,直接强制终止进程,这对于一些比较敏感的服务,例如金融交易等业务是致命的。
比如说程序里使用了Springboot 的 ShutdownHook
钩子函数服务,或者实现了DisposableBean
的接口,来实现服务正常关闭情况时,调用某些方法。如果程序时被kill -9 结束的,这些方法就会不会被调用,进而导致某些问题。
程序中有selenium,使用kill -9的相关问题
前文有说,如果使用kill -9结束进程会使程序无法调用钩子函数。而程序在使用selenium时,往往都会使用钩子函数,在结束程序前,就chrome浏览器进程和selenium的chromedriver驱动进程结束掉,以保证下次启动selenium的正常。
所以如果程序使用了selenium,那就不能使用kill -9来结束程序进程!
解决方案
以下脚本是参考https://zhuanlan.zhihu.com/p/396444861和同事的脚本编写。
#!/bin/bash
APP_FILE=proxyIpCrawl-0.0.1-SNAPSHOT.jar
CONF_NAME=test
JAVA_OPTIONS_INITIAL=-Xms2048M
JAVA_OPTIONS_MAX=-Xmx3072M
APP_NAME=proxyIpCrawl-0.0.1
PID=0
function get_pid {
javaps=`jps -l | grep $APP_FILE`
if [ -n "$javaps" ]; then
PID=`echo $javaps | awk '{print $1}'`
else
PID=0
fi
}
function check_if_process_is_running {
get_pid
if [ $PID -ne 0 ]; then
return 0
fi
return 1
}
function stop {
echo -e "Waiting for process to stop"
get_pid
num=`expr $num + 1`
if [ $PID -ne 0 ]; then
# 重试次数小于3次则继续尝试停止服务
if [ "$num" -le 3 ];then
echo "attempt to kill... num:$num"
kill $PID
sleep 1
else
# 重试次数大于3次,则强制停止
echo "force kill..."
# 结束Chromedriver进程
ps aux | grep chromedriver | grep -v grep | awk '{print $2}' | xargs kill -9
# 结束Chrome进程
ps aux | grep chrome | grep -v grep | awk '{print $2}' | xargs kill -9
# 结束java进程
kill -9 $PID
fi
# 检查上述命令执行是否成功
if [ $? -eq 0 ]; then
echo -e "kill -15 $APP_NAME run finished..."
else
echo -e "kill -15 $APP_NAME run failed..."
fi
# 重新获取进程ID,如果还存在则重试停止
get_pid
if [ $PID -ne 0 ]; then
echo -e "$APP_NAME has running...retry"
stop
fi
else
echo "$APP_NAME not running"
fi
}
case "$1" in
status)
if check_if_process_is_running
then
echo -e "$APP_NAME has running"
else
echo -e "$APP_NAME not ran"
fi
;;
stop)
if ! check_if_process_is_running
then
echo -e "$APP_NAME has stopped"
exit 0
fi
stop
;;
start)
if check_if_process_is_running
then
echo -e "$APP_NAME has running"
exit 1
fi
# 启动命令
nohup java -jar $JAVA_OPTIONS_INITIAL $JAVA_OPTIONS_MAX $APP_FILE --spring.profiles.active=$CONF_NAME &
echo -e "Starting"
for i in {1..20}; do
if ! check_if_process_is_running
then
echo -ne "."
sleep 1
fi
done
if ! check_if_process_is_running
then
echo -e "$APP_NAME launch failed"
else
echo -e "$APP_NAME has started"
fi
;;
restart)
$0 stop
if [ $? = 1 ]
then
exit 1
fi
$0 start
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
esac
exit 0
- 脚本在stop进程时,会尝试执行3次kill -15命令来结束程序进程,kill -15命令就能够让程序正常调起钩子函数让程序完成需要完成的动作。如果3次都没有结束程序在使用kill -9 强制结束进程
- 同时为了结束selenium相关进程,在强制结束进程时,还会使用管道命令将chrome和chromedriver进程一起杀死。如果你的程序没有使用selenium,可以删除这两条管道命令,同时根据你程序的需求自行编写其他命令
- 其他程序使用该脚本只需要修改前五个常量即可