Java Runtime.exec()
我可以从命令行运行这个命令,没有任何问题(validation脚本执行):
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!"); } }
您需要排除进程的输出和错误stream,否则将在执行的程序产生输出时阻塞。
从处理文档 :
由于某些本地平台仅为标准input和输出stream提供有限的缓冲区大小,因此如果不及时写入inputstream或读取子stream程的输出stream,可能会导致subprocess阻塞甚至死锁。
读取(并closures) p.getInputStream()
和p.getErrorStream()
。
例如:
// com.google.common.io.CharStreams CharStreams.toString(new InputStreamReader(p.getInputStream())); CharStreams.toString(new InputStreamReader(p.getErrorStream()));
人们通常被执行例程挂在爪哇。 我也曾经这样做过。 问题是你试图执行的进程可能(取决于很多事情)首先写入stdOut或stdErr。 如果你以错误的顺序处理它们,exec会挂起。 为了正确处理这个问题,你必须创build两个线程来同时读取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();