ProcessBuilder与Runtime.getRuntime()。exec的行为不同

时间:2016-07-16 20:29:16

标签: java io

鉴于代码:

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

1 个答案:

答案 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();