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

Java运行系统命令并忽略输出,java,Java,从Java运行忽略STDOUT和STDERR的系统命令是否有合理的方法?例如,当我尝试以下操作时: Process p = Runtime.getRuntime().exec("some_executable_path param1 param2 >NUL 2>&1"); Java试图解析该命令,最终转义参数(例如,阻止输出重定向)。如果我不重定向STDOUT/STDERR,缓冲区将被填满并阻止系统调用退出。以下内容满足了我的要求,但非常繁琐,并且仅为了丢弃系统调用的输出而

从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的输出?

不是Java“阻止”重定向,它只是没有肯定地阻止重定向,您的程序也没有。当您给CMD一个命令,如
program arg1 arg2>out 2>err 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% 
pb.redirectOutput (new File("NUL")).redirectErrorStream(true)
或者(假设Java7+)告诉
ProcessBuilder
执行重定向:

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% 
pb.redirectOutput (new File("NUL")).redirectErrorStream(true)

您至少应该“吞食”它们,即从流中获取输出,但不要对它们做任何事情,否则您可能会耗尽进程缓冲区(我认为这是它的术语)。这是“如何取悦所有人”的问题之一。您可以编写一小段库代码,简化代码以执行所需的特定任务,这样您就可以在需要时重新使用它,而不必牺牲可移植性。您有两个选项:(1)调用shell来运行命令,此时命令行中的重定向将起作用;或(2)为重定向目标指定
/dev/null
(或目标系统上的任何内容)。根据你的例子,我推断你在Windoze上,这两种黑客都不起作用。JimGarrison:在Windows中,等效的黑客有
[“cmd”、“/c”、“带重定向的命令”]
新文件(“NUL”)
——是的,文件名NUL是全局保留的;CON是/dev/tty和其他几个的等价物。JeffG:不是Java“阻止”重定向,而是Java和您调用的程序都不为
执行重定向,只有CMD或shell执行重定向。@dave_thompson_085所以这应该是一个答案。另外,你对OP的附加评论应该在一个单独的评论中,这样你就可以对他进行\@ping。第二个选项是我使用的,因为它只需要对操作系统的一个依赖项:空设备的名称。这在Windows上是“NUL”,在Linux上是“/dev/null”。我很惊讶这样一个文件不是
file
类上的公共静态常量。类似于
File.NullDevice