2011-12-21 50 views
19

我可以沒有任何問題運行命令行命令(驗證腳本執行):的Java的Runtime.exec()

c:/Python27/python ../feedvalidator/feedvalidator/src/demo.py https://das.dynalias.org:8080/das_core/das/2.16.840.1.113883.4.349/1012581676V377802/otherAdminData/careCoordinators 

,並從Java,如果我離開過的URL參數,只是做:

String[] args1 = {"c:/Python27/python", "../feedvalidator/feedvalidator/src/demo.py" }; 
Runtime r = Runtime.getRuntime(); 
Process p = r.exec(args1); 

它工作正常。如果我使用某些參數的URL如:

String[] args1 = {"c:/Python27/python", "../feedvalidator/feedvalidator/src/demo.py" , "http://www.intertwingly.net/blog/index.atom"}; 
// or 
String[] args1 = {"c:/Python27/python", "../feedvalidator/feedvalidator/src/demo.py" , "http://www.cnn.com"}; 

它也正常工作。

但是,如果我使用這個特定的URL https://das.dynalias.org:8080/das_core/das/2.16.840.1.113883.4.349/1012581676V377802/otherAdminData/careCoordinators,那麼腳本只是掛起(Java等待過程完成)。我不知道爲什麼它從該URL的命令行工作,但不是從一個Java程序。我試圖添加引號來圍繞URL參數,但這也不起作用。我在URL中看不到任何我認爲需要轉義的字符。

全碼:

String urlToValidate = "https://das.dynalias.org:8080/das_core/das/2.16.840.1.113883.4.349/1012581676V377802/otherAdminData/careCoordinators"; 

String[] args1 = {"c:/Python27/python", "C:/Documents and Settings/vhaiswcaldej/DAS_Workspace/feedvalidator/feedvalidator/src/demo.py", urlToValidate }; 
System.out.println(args1[0] + " " + args1[1] + " " + args1[2]); 

Runtime r = Runtime.getRuntime(); 
Process p = r.exec(args1); 
BufferedReader br = new BufferedReader(new InputStreamReader(
p.getInputStream())); 
int returnCode = p.waitFor(); 
System.out.println("Python Script or OS Return Code: " + Integer.toString(returnCode)); 
if (returnCode >= 2) { 
    .out.println("OS Error: Unable to Find File or other OS error."); 
    } 

String line = ""; 
while (br.ready()) { 
    String str = br.readLine(); 
    System.out.println(str); 
    if (str.startsWith("line")) { 
    //TODO: Report this error back to test tool. 
    //System.out.println("Error!"); 
    } 
    } 
+0

也許當前目錄確實重要嗎?你可以嘗試在命令行切換到另一個目錄。 – Yogu 2011-12-21 20:19:44

+0

你應該檢查在Linux上執行的實際命令行 - 'ps f',在Win - sysinternals ProcessExplorer – 2011-12-21 20:26:51

+1

這可能是一個ssl問題。你可以嘗試調用一個http端點來驗證它嗎? – phoet 2011-12-21 20:57:12

回答

17

你需要排泄過程的輸出和錯誤流,否則當執行程序產生輸出它會阻止。

Process documentation

由於某些本地平臺只提供用於標準輸入和輸出流有限緩衝區的大小,沒有及時寫輸入流或讀出的子過程的輸出流可能會導致子進程阻塞甚至死鎖。

+0

我沒有看到這個過程的排水方法。我會實際運行哪些代碼?我已經用完整的代碼更新了這個問題。 – user994165 2011-12-21 22:45:11

+1

來排除輸出和錯誤流只是:InputStream in = ...; in.skip(in.available()); InputStream err = ...; err.skip(err.available()); – 2011-12-21 22:50:42

+1

@ user994165這裏有示例代碼,用於排除流[這裏](http://stackoverflow.com/a/7962434/523391) – prunge 2011-12-22 01:12:49

7

閱讀與())p.getInputStream() and p.getErrorStream()

例如:

// com.google.common.io.CharStreams 
CharStreams.toString(new InputStreamReader(p.getInputStream())); 
CharStreams.toString(new InputStreamReader(p.getErrorStream())); 
+0

如果輸出大於Java的堆內存,該怎麼辦?雖然我猜在大多數情況下,你知道它不會。如果你寫這樣一個方法,可能會出現一個問題,然後在你忘記這個限制之後在產生大輸出的東西上使用它。 – 2014-12-11 08:41:57

+0

@EvgeniSergeev沒錯,以另一種方式閱讀和關閉它們,我剛剛提到它們作爲示例。使用redirectErrorStream的 – 2014-12-11 15:24:04

7

人們通常得到了由Java中的exec例程掛起抓獲。我也曾經這麼做過。問題是你正在嘗試執行的進程可能(取決於很多事情)首先寫入stdOut或stdErr。如果你以錯誤的順序處理它們,exec會掛起。要正確處理此問題,您必須創建2個線程來同時讀取stdErr和stdOut 。如:

Process proc = Runtime.getRuntime().exec(cmd); 

// handle process' stdout stream 
Thread out = new StreamHandlerThread(stdOut, proc.getInputStream()); 
out.start(); 

// handle process' stderr stream 
Thread err = new StreamHandlerThread(stdErr, proc.getErrorStream()); 
err.start(); 

exitVal = proc.waitFor(); // InterruptedException 

... 

out.join(); 
err.join(); 
+1

是一個更好的主意:http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ProcessBuilder.html#redirectErrorStream%28boolean%29 – 2013-04-03 05:23:53

相關問題