寫問題之前,大家不妨跟我做個小實驗,直接運行一個腳本:
temp.sh
內容只有一行:sleep 1000 &
運行temp.sh,sleep進程在后臺運行,使用ps -ef | grep sleep得到sleep的PID,使用 kill -SIGINT PID,無效,kill -SIGQUIT PID,無效,kill -SIGHUP PID,成功
正文
今天上線發生了一個故障,大概為:從腳本中啟動tomcat,然后退出終端,tomcat退出,然而我們并不知道,當發現的時候,發現線上的tomcat進程都沒了。
原因是因為,使用腳本啟動,腳本中關鍵的有兩句:
start_tomcat.sh #啟動tomat
tail -f search.log #查看日志
而那個start_tomcat.sh,創建了tomcat的后臺進程,在執行tail -f search.log 的時候,整個腳本還沒有退出,這時關閉了終端,終端會發送 SIGHUP 信號到腳本,后臺進程也收到了信號,Java程序沒有對 SIGHUP 信號作特殊處理,所以Linux默認終止程序。
后來我們發現,如果在運行腳本的時候,按Ctrl + C ,也就是發送 SIGINT 信號到腳本,tomcat后臺進程依舊收到了 SIGINT(可以使用 strace -e trace=singal -p 進程ID監視進程的信號處理),但是tomcat卻沒有退出,查詢資料后發現是因為:
Linux對于腳本中啟動的后臺進程,將進程的 SIGINT 信號的處理函數改為了 SIGIGN ,即忽略,其實,除了SIGINT,SIGQUIT 的處理也是一樣的。
在整個腳本沒有退出的情況下,按Ctrl + C,進程收到 SIGINT 信號,但是處理函數是忽略,所以tomcat沒有退出,而退出終端,發送的信號是 SIGHUP,tomcat收到后,自己停止。
參考: