2010-07-19 83 views
28

我一直在嘗試使用Java的ProcessBuilder在Linux中啓動應該運行「長期」的應用程序。這個程序運行的方式是啓動一個命令(在這種情況下,我啓動一個媒體播放應用程序),允許它運行,並檢查以確保它沒有崩潰。例如,檢查PID是否仍然有效,然後重新啓動進程,如果它已經死亡。Java ProcessBuilder:結果進程掛起

我現在得到的問題是,PID在系統中保持活動狀態,但應用程序的GUI掛起。我嘗試將ProcessBuilder(cmd).start()轉換爲一個單獨的線程,但似乎並沒有解決任何問題,正如我所希望的那樣。

基本上結果是,對於用戶來說,程序APPEARS崩潰了,但是殺死驅動ProcessBuilder.start()進程的Java進程實際上允許創建的進程恢復其正常行爲。這意味着Java應用程序中的某些內容正在干擾生成的進程,但我完全不知道這一點。 (因此,爲什麼我試圖將它分離成另一個線程,似乎沒有解決任何問題)

如果任何人有任何輸入/想法,請讓我知道,因爲我不能爲我的生活想到如何解決這個問題。

編輯:我不關心從流程創建的I/O流,因此沒有采取任何措施來解決這個問題 - 這是否會導致流程本身掛起?

+3

既然你已經說過你沒有處理流程的流程,我必須插話說「是的,這很可能是問題的原因。閱讀是很重要的標準輸出和標準錯誤的內容,並且如果孩子希望你寫入標準輸入「」。這將是值得您一陣子檢查這個問題:http://stackoverflow.com/questions/882772/capturing-stdout-when-calling-runtime-exec/882795#882795 – 2010-07-19 22:07:50

回答

30

如果進程寫入stderr或stdout,並且沒有讀取它 - 它只會「掛起」,寫入stdout/err時會被阻塞。無論是使用shell將stdout /犯錯到/ dev/null或與redirectErrorStream(真)合併標準輸出/ ERR和產卵另一個線程從過程

+5

看起來非常重要!你必須從ffmpeg消費stdout/stderr。至少我注意到如此發佈/消費rtmp連接。 – Nicholi 2012-08-30 18:09:16

2

編輯:我不關心從流程創建的I/O流,因此沒有采取任何措施來解決這個問題 - 是否會導致流程本身掛起?

如果您不讀取進程創建的輸出流,那麼一旦應用程序的緩衝區已滿,應用程序可能會阻塞。我從未在Linux上看到過這種情況(儘管我並不是說它沒有),但我在Windows上看到了這個確切的問題。我認爲這可能是相關的。

11

的讀取標準輸出你想要把戲?

不要從ProcessBuilder.start()開始您的過程。不要試圖從Java的流重定向/消費混亂(尤其是如果你沒有給它關於它;)

使用ProcessBuilder.start()啓動一個小的shell腳本,吞噬所有的輸入/輸出流。

類似的東西:

#!/bin/bash 

nohup $1 >/dev/null 2>error.log & 

那就是:如果你不關心stdout和仍想記錄標準錯誤(你呢?)到一個文件中(error.log中這裏)。

如果你甚至不關心標準錯誤,只需將其重定向到stdout:

#!/bin/bash 

nohup $1 >/dev/null 2>1 & 

你調用從Java腳本微小,給它作爲一個參數要運行的進程的名稱。

如果在Linux上運行的進程被重定向標準輸出和標準錯誤到/ dev/null的仍然產生什麼那麼你已經有了破損,不符合一,Linux下安裝;)

換句話說:上述Just Works [TM]並擺脫有問題的「你需要消耗這個流,並且該命令bla bla bla Java特定的無意義」

+0

得到了我們很好的笑聲 - 現在是星期五晚上,這花費我們我們的晚上:) – 2017-03-24 20:13:06

5

在我遇到過類似的問題後,我偶然發現了這個問題。同意nos,你需要處理輸出。我有這樣的事情:

ProcessBuilder myProc2 = new ProcessBuilder(command); 
final Process process = myProc2.start(); 

它工作得很好。產卵過程甚至沒有輸出一些輸出,但沒有太多。當我開始輸出更多東西時,看起來我的程序甚至不再被啓動。我更新到:

ProcessBuilder myProc2 = new ProcessBuilder(command); 
myProc2.redirectErrorStream(true);   
final Process process = myProc2.start(); 
InputStream myIS = process.getInputStream(); 
String tempOut = convertStreamToStr(myIS); 

它又開始工作了。 (請參閱此鏈接convertStreamToStr()代碼:http://singztechmusings.wordpress.com/2011/06/21/getting-started-with-javas-processbuilder-a-sample-utility-class-to-interact-with-linux-from-java-program/

11

運行進程的線程可能會阻止,如果它不處理輸出。這可以通過產生一個讀取進程輸出的新線程來完成。

final ProcessBuilder builder = new ProcessBuilder("script") 
        .redirectErrorStream(true) 
        .directory(workDirectory); 

    final Process process = builder.start(); 
    final StringWriter writer = new StringWriter(); 

    new Thread(new Runnable() { 
     public void run() { 
      IOUtils.copy(process.getInputStream(), writer); 
     } 
    }).start(); 

    final int exitValue = process.waitFor(); 
    final String processOutput = writer.toString(); 
+0

線程似乎並沒有結束 – user1120007 2015-01-29 09:38:15

0

如果您需要捕獲輸出和錯誤和監視然後用Apache Commons Exec幫了我不少的過程。

0

我認爲問題在於Linux本身的緩衝管道。

嘗試使用stdbuf與可執行

new ProcessBuilder().command("/usr/bin/stdbuf","-o0","*executable*","*arguments*");** 

-o0說不要緩衝輸出。 如果要解除輸入和錯誤管道的緩衝區,請同樣輸入-i0-e0