由于正常关闭(viaport)的话会在 pause 以前有这样的一句warn日志:java
org.apache.catalina.core.StandardServer await A valid shutdown command was received via the shutdown port. Stopping the Server instance. 而后才是 pause -> stop -> destroy
而这又有两种状况,一是应用代码里有地方用System.exit
来退出jvm,二是系统发的信号(kill -9
除外,SIGKILL信号JVM不会有机会执行shutdownhook)shell
先经过排查代码,应用方和中间件团队都排查了System.exit
在这个应用中使用的可能。那就只剩下Signal的状况了;通过一番排查后,发现每次tomcat意外退出的时间与ssh会话结束的时间正好吻合。apache
有了这个线索以后,银时同窗马上看了一下对方测试环境的脚本,简化后以下:tomcat
$ cat test.sh #!/bin/bash cd /data/server/tomcat/bin/ ./catalina.sh start tail -f /data/server/tomcat/logs/catalina.out
tomcat启动为后,当前shell进程并无退出,而是挂住在tail进程,往终端输出日志内容。这种状况下,若是用户直接关闭ssh终端的窗口(用鼠标或快捷键),则java进程也会退出。而若是先ctrl-c
终止test.sh进程,而后再关闭ssh终端的话,则java进程不会退出。bash
这是一个有趣的现象,catalina.sh start
方式启动的tomcat会把java进程挂到init
(进程id为1)的父进程下,已经与当前test.sh
进程脱离了父子关系,也与ssh进程没有关系,为何关闭ssh终端窗口会致使java进程退出?ssh
若是咱们在test.sh里设置开启做业控制的话,就不会让java进程退出了jvm
#!/bin/bash set -m cd /home/admin/tt/tomcat/bin/ ./catalina.sh start tail -f /home/admin/tt/tomcat/logs/catalina.out
此时java后台进程继承父进程catalina.sh的pgid,而catalina.sh再也不使用test.sh的进程组,而是本身的pid做为pgid,catalina.sh进程在执行完退出后,java进程挂到了init下,java与test.sh进程就彻底脱离关系了,bash也不会再向它发送信号。测试
详情参考:http://hongjiang.info/why-kill-2-cannot-stop-tomcat/,写的很详细。日志