2011-12-21 25 views
19

tôi có thể chạy lệnh này từ dòng lệnh mà không cần bất kỳ vấn đề (kịch bản xác nhận thực hiện):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 

và từ java nếu tôi rời khỏi tham số URL và chỉ cần làm:

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

hoạt động tốt. Nếu tôi sử dụng các URL nhất định cho thông số như:

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"}; 

nó cũng hoạt động tốt.

Nhưng nếu tôi sử dụng URL cụ thể này https://das.dynalias.org:8080/das_core/das/2.16.840.1.113883.4.349/1012581676V377802/otherAdminData/careCoordinators thì tập lệnh chỉ bị treo (java chờ quá trình kết thúc). Tôi không chắc chắn lý do tại sao nó hoạt động từ dòng lệnh cho URL đó nhưng không phải từ một chương trình java. Tôi đã thử thêm dấu ngoặc kép để bao quanh thông số URL nhưng điều đó cũng không hoạt động. Tôi không thấy bất kỳ ký tự nào trong URL mà tôi cho rằng cần phải được thoát.

Full Code:

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

Có thể thư mục hiện tại không quan trọng? Bạn có thể thử chuyển sang thư mục khác trong dòng lệnh. – Yogu

+0

bạn nên kiểm tra dòng lệnh thực tế đang được thực hiện từ Java, trên Linux - 'ps f', trên Win - sysinternals ProcessExplorer –

+1

điều này có thể là một số vấn đề ssl. bạn có thể thử gọi một điểm cuối http để xác minh nó không? – phoet

Trả lời

17

Bạn cần phải lấy nước từ các đầu ra và lỗi suối của quá trình, hoặc nếu không nó sẽ chặn khi chương trình thực hiện sản xuất đầu ra.

Từ Process documentation:

Bởi vì một số nền tảng bản địa chỉ cung cấp kích thước bộ đệm hạn chế cho đầu vào và đầu ra suối chuẩn, thất bại trong việc kịp thời viết dòng đầu vào hoặc đọc các dòng đầu ra của tiến trình con có thể làm cho tiến trình con để chặn và thậm chí bế tắc.

+0

Tôi không thấy phương pháp thoát cho quy trình. Tôi sẽ chạy mã nào? Tôi đã cập nhật câu hỏi với mã đầy đủ. – user994165

+1

để thoát đầu ra và luồng lỗi chỉ cần thực hiện: InputStream in = ...; in.skip (in.available()); InputStream err = ...; err.skip (err.available()); –

+1

@ user994165 có mã mẫu để thoát luồng [tại đây] (http://stackoverflow.com/a/7962434/523391) – prunge

7

Đọc (và đóng) p.getInputStream()p.getErrorStream().

Ví dụ:

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

Điều gì xảy ra nếu đầu ra lớn hơn bộ nhớ heap của Java? Mặc dù tôi đoán trong hầu hết các trường hợp bạn biết nó sẽ không được. Một vấn đề có thể phát sinh nếu bạn viết một phương pháp như thế này, và sau đó sử dụng nó trên một cái gì đó sản xuất sản lượng lớn sau khi bạn quên giới hạn này. –

+0

@EvgeniSergeev Đúng vậy, đọc và đóng chúng theo cách khác, tôi chỉ đề cập đến chúng như là ví dụ. –

7

dân thường bị bắt bởi treo thói quen exec trong Java. Tôi cũng đã từng bị một lần như vậy. Vấn đề là quá trình bạn đang cố gắng thực hiện có thể (tùy thuộc vào nhiều thứ) hoặc là viết đầu tiên vào stdOut hoặc stdErr. Nếu bạn xử lý chúng theo thứ tự sai thì exec sẽ bị treo. Để xử lý đúng cách này, bạn phải tạo 2 luồng để đọc stdErr và stdOut đồng thời. Giống như:

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

sử dụng chuyển hướngErrorStream là một ý tưởng tốt hơn nhiều: http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ProcessBuilder.html#redirectErrorStream%28boolean%29 –

Các vấn đề liên quan