好的 - 這對很多人來說都有點問題 - 因爲我還沒有看到有效的答案,所以我想我會表達這個問題,這樣一個想出來的人可以告訴我們其他人。在Java中執行外部命令的經典問題?
問題是,下面三個工作中的兩個工作只是罰款代碼。
reader3的實例演示了這個問題。 Reader3無法讀取成功啓動外部文件的結果。試圖在任一標準輸入或標準錯誤的InputStream塊永遠做任何類型的讀取(realine等):
package Problems;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class RunningProblem {
public static class RunningReader implements Runnable {
private Process proc;
private String sName;
private RunningReader(Process proc1, String sName) {
this.proc = proc1;
this.sName = sName;
}
public void run() {
try {
// InputStreamReader in = new InputStreamReader(proc.getInputStream());
// BufferedReader reader = new BufferedReader(in);
InputStreamReader err = new InputStreamReader(proc.getErrorStream());
BufferedReader reader = new BufferedReader(err);
String line = reader.readLine();
while (line != null) {
System.out.println(sName + ": " + line);
line = reader.readLine();
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(3);
try {
Runtime rt = Runtime.getRuntime();
Process proc1 = rt.exec("ps ax");
RunningReader reader1 = new RunningReader(proc1, "reader1");
Process proc2 = rt.exec("ls -l /");
RunningReader reader2 = new RunningReader(proc2, "reader2");
Process proc3 = rt.exec("/bin/tar");
RunningReader reader3 = new RunningReader(proc3, "reader3");
pool.execute(reader3);
pool.execute(reader2);
pool.execute(reader1);
} catch (Exception ex) {
System.err.println(ex.getMessage());
} finally {
pool.shutdown();
}
System.out.println("Launcher.main() Exited.");
}
}
你確定你的/斌/焦油打印到標準錯誤(而不是標準輸出),並且你確定/斌/焦油,當它連接到一個管道確實停止? – nos 2011-03-05 18:39:00
我正在研究的一個應用程序每天都在做這個,在數百個不同的機器上......我可以告訴你**一件**事情:有*方式*太多陷阱。我們最終確保不會讀取或寫入任何流。除此之外,我們從Java產生的過程本身也產生了另一個過程,所以我們可以從Java中終止第一個過程(過一段時間)。然後我們使用IPC的臨時文件。所以基本上我們在*「nohup ...&」*調用中包裝了任何外部進程調用(這也可以用來重定向stdout/stderr)。 – SyntaxT3rr0r 2011-03-05 19:03:06
它有點糟糕,因爲我們需要輪詢臨時文件,但是它非常容易。只要閱讀試圖簡化* Runtime.getRuntim()。exec *)的各種API就必須說明從Java啓動外部進程:這是一個巨大的,混亂的,慘敗。如果你不想像我們那樣激進,那麼至少應該使用像Apache Commons exec *這樣的東西,並且閱讀他們對於從Java運行外部進程相當悲傷的狀態的看法。 :) – SyntaxT3rr0r 2011-03-05 19:06:04