背景
由于应用项目及其复杂,应用自己开启的线程在tomcat停止时没有关闭,便会导致tomcat进程没有终止。但是tomcat监听的端口却已经释放,因为执行shutdown.sh脚本时,tomcat自身服务会关闭,但是由于应用中还存在非守护线程,于是JVM进程(即tomcat进程)便不会退出。这时候再次执行startup.sh脚本时,不会报端口占用的错,甚至还是同一个进程,就会发生诡异的事情,可能明明应用中只有一个名为a的线程,然后通过jstack命令打印堆栈会发现名为a的线程出现多次。
强制杀死tomcat进程
通过阅读catalina.sh脚本,可以看到文件最后有如下提示信息
echo "Usage: catalina.sh ( commands ... )"
echo "commands:"
if $os400; then
echo " debug Start Catalina in a debugger (not available on OS400)"
echo " debug -security Debug Catalina with a security manager (not available on OS400)"
else
echo " debug Start Catalina in a debugger"
echo " debug -security Debug Catalina with a security manager"
fi
echo " jpda start Start Catalina under JPDA debugger"
echo " run Start Catalina in the current window"
echo " run -security Start in the current window with security manager"
echo " start Start Catalina in a separate window"
echo " start -security Start in a separate window with security manager"
echo " stop Stop Catalina, waiting up to 5 seconds for the process to end"
echo " stop n Stop Catalina, waiting up to n seconds for the process to end"
echo " stop -force Stop Catalina, wait up to 5 seconds and then use kill -KILL if still running"
echo " stop n -force Stop Catalina, wait up to n seconds and then use kill -KILL if still running"
echo " configtest Run a basic syntax check on server.xml - check exit code for result"
echo " version What version of tomcat are you running?"
echo "Note: Waiting for the process to end and use of the -force option require that \$CATALINA_PID is defined"
可以看到通过-force选项强行杀死tomcat进程,也就是说先正常关闭tomcat进程,等待5秒(默认值)后如果进程还在则使用kill -9的方式强制杀死进程。
但是使用-force选项时需要CATALINA_PID这个变量存在。
tomcat可以在bin目录下的setenv.sh文件里指定变量的值,catalina.sh脚本执行时会导入该文件中的变量,这样就可以不用修改catalina.sh文件了
第一步
在bin目录下新建setenv.sh文件,指定CATALINA_PID的值,注意CATALINA_PID是一个文件,而内容才是PID进程号
CATALINA_PID=$CATALINA_HOME/bin/CATALINA_PID
第二步
修改shutdown.sh文件,在最后一行添加-force选项
# 原来是exec "$PRGDIR"/"$EXECUTABLE" stop "$@"
exec "$PRGDIR"/"$EXECUTABLE" stop 10 -force "$@"
效果
sh startup.sh
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr/local/java/jdk1.8.0_181
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Using CATALINA_PID: /usr/local/tomcat/bin/CATALINA_PID
Tomcat started.
sh shutdown.sh
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr/local/java/jdk1.8.0_181
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Using CATALINA_PID: /usr/local/tomcat/bin/CATALINA_PID
Tomcat stopped.