2011-03-02 69 views
5

我開始在我的Java程序(在Linux上)的外部進程,我需要能夠發送一個SIGTERM信號而不是發送的SIGKILL。有沒有一種方法可以更好地阻止以commons-exec開始的unix進程?或者我可以獲得PID,以便我可以自己運行適當的kill命令?優雅的殺死Apache Commons Exec進程

回答

6

那麼,Commons Exec依賴於Java Process類,它不公開PID。這也是用來殺死進程的東西,所以它不是你可以改變行爲的東西。所有漂亮和封裝。得愛OO,呃?

如果您只是將進程啓動到後臺,您可以將它們封裝在一個簡單的shell腳本中,爲您捕獲PID,然後將其保存到Java例程知道的「已知位置」。仍然有點混亂,而且,它自然不會很好地移植到其他平臺上。

您可以使用JNI編寫自己的exec函數來爲您捕獲這些信息,但這可能不那麼友好。

你可以編寫一個特定於平臺的exec啓動程序守護進程,以更加面向系統的方式(C,Python等)。您發送IT消息來啓動和停止事情,併爲您處理該過程。這樣做的一個好處是,當你運行一個新進程時(根據你的JVM的大小,這可能會相當昂貴),你不必分叉JVM。

你可以在開始時啓動守護進程並共享一個套接字或管道(兩者都非常便攜)。這實際上並不是一個可怕的INelegant解決方案,它劃分了很多系統特定的行爲(所以你可以有一個完全不同的進程,比如Windows和Unix,並且你的Java保持不變,你只需要移植你的小守護進程),而不必運行JNI。

+0

是的,這是一個從shell腳本執行java jar的好主意,所以你知道要殺死哪一個java jar。 +1 – ant

+0

好的,謝謝你的信息。真的很奇怪,他們沒有公開這種功能,我只需要在python中解決它。遊民。 – jtb

0

那麼你可以用grep顯示它,爲前:

for i in $(ps -ef | grep -i "[Y]ourClassName" | awk '{print $2}'); do kill -9 $i; done 

這是已經將它運行超過1次(儘管它,如果你只有一個項目工程)的情況下,請注意[]中grep,那麼grep不會給你自己的進程pid,而-i代表忽略大小寫,awk僅用於打印第二列,即PID號。

+1

這是可能的,但我必須運行同一腳本的多個invokations,和我d真的只是停止外部進程開始的確切的一個,而不是嘗試使用命令行將它們再次鏈接在一起。我認爲沒有辦法從commons-exec獲取PID? – jtb

+0

@jtb如果你問我,Will Hartung會有一個更好的想法,就是用shell腳本包裝你的jar,你仍然可以使用這個grep或者另一個來殺死你想要的。 – ant

6

ExecuteWatchdog類有殺死進程的方法。

所以,你可以只創建一個長期超時看門狗,並用它neccessary時殺死進程,即

executor.getWatchdog().destroyProcess(); 
+1

對,但發送SIGKILL。問題是如何發送不同的信號,如SIGTERM,以更優雅地停止它。 – jtb

+3

@audras實際上,你最好使用'新的ExecuteWatchdog(ExecuteWatchdog.INFINITE_TIMEOUT)',而不僅僅是* long * timeout。 –