由於正常關閉(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/,寫的很詳細。日誌