Java Runtime.exec()

use*_*165 20 java

我可以从命令行运行此命令而没有任何问题(验证脚本执行):

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 
Run Code Online (Sandbox Code Playgroud)

如果我省略了URL参数,那么从java中执行:

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

它工作正常.如果我使用某些参数的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"};
Run Code Online (Sandbox Code Playgroud)

它也工作正常.

但是如果我使用这个特定的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!");
     }
     }
Run Code Online (Sandbox Code Playgroud)

pru*_*nge 18

您需要耗尽进程的输出和错误流,否则它将在执行的程序生成输出时阻塞.

来自Process文档:

由于某些本机平台仅为标准输入和输出流提供有限的缓冲区大小,因此无法及时写入输入流或读取子进程的输出流可能导致子进程阻塞甚至死锁.

  • @user994165 有用于排流流的示例代码 [here](http://stackoverflow.com/a/7962434/523391) (2认同)

Ali*_*iba 7

阅读(并关闭)p.getInputStream()p.getErrorStream().

例如:

// com.google.common.io.CharStreams
CharStreams.toString(new InputStreamReader(p.getInputStream()));
CharStreams.toString(new InputStreamReader(p.getErrorStream()));
Run Code Online (Sandbox Code Playgroud)


Art*_*tur 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();
Run Code Online (Sandbox Code Playgroud)

  • 使用redirectErrorStream是一个更好的主意:http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ProcessBuilder.html#redirectErrorStream%28boolean%29 (2认同)