Java运行系统命令和忽略输出

时间:2017-03-14 23:53:32

标签: java

是否有任何理智的方法从Java运行忽略STDOUT和STDERR的系统命令?例如,当我尝试以下操作时:

Process p = Runtime.getRuntime().exec("some_executable_path param1 param2 >NUL 2>&1");

Java尝试解析命令,并最终转义参数(例如,阻止输出被重定向)。如果我没有重定向STDOUT / STDERR,则缓冲区会填满并阻止系统调用退出。以下是我想要的,但是非常麻烦并且创建昂贵的资源只是为了抛弃系统调用的输出:

ProcessBuilder pb = new ProcessBuilder("some_executable_path", "param1", "param2");
pb.redirectErrorStream(true);
final Process p = pb.start();
final Thread redirectToNull = new Thread(() -> {
        final InputStream stdout = process.getInputStream();
        try {
            while (stdout.read() != -1);
        } catch (final Exception e) {
            // Don't care
        }
    }, "Output Consumer Thread");
redirectToNull.setDaemon(true);
redirectToNull.start();

我意识到Java设计团队被称为自虐,但这很荒谬。我更愿意提供一个批处理或Perl脚本,用我的应用程序包装系统调用,而不是使用上面的代码。必须有一种更简单的方法来实现这一目标。

所以问题是,是否有任何理智的方法从Java中运行系统命令并忽略打印到STDOUT / STDERR的输出?

1 个答案:

答案 0 :(得分:5)

并不是说Java'阻止'重定向,它只是没有肯定地做,而且你的程序也没有。当您向CMD提供program arg1 arg2 >out 2>err <in之类的命令时,CMD会设置这些重定向,然后只使用program 调用arg1 arg2,而不是>out在Unix上,shell执行相同的操作 - 可以选择多个shell,但是它们都像这样处理重定向。类似地,管道由CMD或shell设置,而不是由那些管道中运行的任何一个或所有程序设置。

因此,在Windows上,执行此操作的方法是运行CMD并让它执行重定向:

Process p = new ProcessBuilder ("cmd", "/c", "program arg1 arg2 >NUL 2>&1").start();
// this uses CMD's default parsing for args, so they must not contain space
// unless you insert 'data' quotes, or things that look like a substitutable %var% 

或(假设Java7 +)告诉ProcessBuilder进行重定向:

pb.redirectOutput (new File("NUL")).redirectErrorStream(true)