鉴于代码:
extend DBTestCase
当我运行代码时,它将执行public String execCommand(String command, File folder) {
if (folder.isDirectory() && Files.isDirectory(folder.toPath())) {
logger.info("It is a directory!"); //yes, is a directory!
}
try {
Process runtimeProc = Runtime.getRuntime().exec(command, null, folder);
Process builderProc = new ProcessBuilder(command)
.directory(folder)
.redirectErrorStream(true)
.start();
} catch (InterruptedException | IOException e) {
logger.log(Level.SEVERE, e, e::getMessage);
throw new IllegalStateException(e);
}
}
而没有问题,但runtimeProc
将抛出IOException:
无法运行程序" myexecutable" (在目录中 " / home / testing / 1acbcd01-76d2-4981-8fd3-b863d6f9ede8"):错误= 20,不是 directory:java.io.IOException:无法运行程序" myexecutable action" (在 目录" / home / testing / 1acbcd01-76d2-4981-8fd3-b863d6f9ede8"): 错误= 20,不是目录
阅读完代码后,我注意到内部builderProc
使用了Runtime.exec()
类。如果一方正在工作而另一方正在抛出异常,这怎么可能?更重要的是:如何修复它?
调试"爆炸点"在jdk' s ProcessBuilder
类内部:
ProcessBuilder
Full StackTrace:
try {
return ProcessImpl.start(cmdarray,
environment,
dir,
redirects,
redirectErrorStream);
} catch (IOException | IllegalArgumentException e) {
String exceptionInfo = ": " + e.getMessage();
Throwable cause = e;
if ((e instanceof IOException) && security != null) {
// Can not disclose the fail reason for read-protected files.
try {
security.checkRead(prog);
} catch (SecurityException se) {
exceptionInfo = "";
cause = se;
}
}
// It's much easier for us to create a high-quality error
// message than the low-level C code which found the problem.
throw new IOException(
"Cannot run program \"" + prog + "\""
+ (dir == null ? "" : " (in directory \"" + dir + "\")")
+ exceptionInfo,
cause);
}
答案 0 :(得分:1)
我发现了不同之处:
默认情况下Runtime.getRuntime().exec
会对输入进行标记,在ProcessBuilder
的情况下,它将按原样执行命令(即:不会标记化)
这就是Runtime
版本可以正常工作的原因,它会将命令分离为:
["buildr", "run"]
另一方面ProcessBuilder
将运行为:["buildr run"]
。
解决方案:在使用ProcessBuilder
之前进行标记,例如:
String[] cmdAsTokens = command.split(" ");
Process process = new ProcessBuilder(cmdAsTokens)
.directory(folder)
.redirectErrorStream(true)
.start();