在本地調試agent相關功能,需要經常性的殺掉Java進程,驗證一些極端情況。
每次都是本能執行如下步驟
- jps
- kill -9 <pid>
- reboot
有一次驗證,發現代碼中添加的ShutdownHook
沒有生效,難道和kill
命令后面的數字有關?
經過一番查閱,后面的數字代表的是具體信號,kill
命令可將指定的信號發送給相應的進程,linux中常見的信號如下:
- 1 SIGHUP 掛起進程
- 2 SIGINT 終止進程
- 3 SIGGQUIT 停止進程
- 9 SIGKILL 無條件終止進程
- 15 SIGTERM 盡可能終止進程
- 17 SIGSTOP 無條件停止進程,但不是終止
- 18 SIGTSTP 停止或者暫停進程,但不終止進程
- 19 SIGCONT 繼續運行停止的進程
kill
命令默認情況使用15,下面我們驗證下使用不同信號,有什么不同的表現。
創建一個springBoot應用
啟動類如下,添加了一個鈎子函數,當進程關閉時,將會調用該鈎子函數。
@SpringBootApplication
public class Server {
public static void main(String[] args) {
SpringApplication.run(Server.class);
<span class="token class-name">Runtime</span><span class="token punctuation">.</span><span class="token function">getRuntime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">addShutdownHook</span><span class="token punctuation">(</span><span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">new</span></span></span></span> <span class="token class-name">Thread</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
<span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@Override</span></span></span></span>
<span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">run</span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span><span class="token punctuation">{</span>
<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"do ShutdownHook.......... "</span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
}
你可以通過
java -jar ~/project/web/target/demo-1.0.jar
也可以加上nohup + &啟動
nohup java -jar ~/project/web/target/demo-1.0.jar &
通過后者啟動,可以看到啟動所在的目錄多了一個文件nohup.out,該文件記錄了應用啟動運行過程中的日志。
&表示以后台方式運行應用。但如果退出關閉啟動的控制台,進程將會停止。
nohup + &也是以后台方式運行應用,但是退出關閉啟動的控制台,進程不會停止,且進程日志將會輸出到nohup.out中。
kill -3
通過執行jps 拿到對應的pid

並執行 kill -3 5085
,驚奇的發現,Java進程並沒有被殺掉,而是打印了一堆線程信息。

kill -9
上一步的 kill -3
並沒有成功的把進程殺掉,我們繼續使用之前的pid。
這次執行 kill -9 5085

執行完 -9,java進程消失了,只留下這么一段話。
kill -15
最后,再試試 kill -15
,猶豫Java進程已經被 -9 給kill了,需要重新啟動一次。

這一次,它打印了鈎子函數中的信息,隨之進程也消失了。
總結
kill -3 <pid> 這玩意一般用不到,可以打印當前進程的線程信息,但是不會關閉Java應用!
kill -9 <pid> 很暴力,不會調用鈎子函數ShutdownHook。
kill <pid> 也就是kill -15 <pid> 很柔和,將會調用鈎子函數ShutdownHook,一般ShutdownHook中會進行一些操作,比如保存數據,關閉連接等。