Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Run System Command and Ignore Output

Tags:

java

Is there any sane way to run a system command from Java that ignores STDOUT and STDERR? For example, when I try the following:

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

Java tries to parse the command, and ends up escaping the arguments (e.g., prevents the output from being redirected). If I don't redirect STDOUT/STDERR, the buffers fill up and prevent the system call from exiting. The following does what I want, but is extremely cumbersome and creates expensive resources just to throw the output of the system call away:

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

I realize the Java design team is known to be masochistic, but this is ridiculous. I would prefer to deliver a batch or Perl script that wraps the system call with my application rather than use the above code. There has to be an easier way to accomplish this.

So the question is, is there any sane way to run a system command from within Java and ignore the output printed to STDOUT/STDERR?

like image 910
Jeff G Avatar asked Jan 04 '23 08:01

Jeff G


1 Answers

It's not that Java 'prevents' redirection, it just doesn't affirmatively do it, and neither does your program. When you give CMD a command like program arg1 arg2 >out 2>err <in, it is CMD that sets up those redirections and then invokes program with arg1 arg2 only, not >out etc. On Unix the shells do the same -- there is a choice of several shells, but all of them handle redirection like this. Similarly pipes are set up by CMD or shells, not by either or all of the programs run in those pipes.

Thus on Windows the way to do this is either run CMD and have it do the redirections:

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% 

or (assuming Java7+) tell ProcessBuilder to do the redirections:

pb.redirectOutput (new File("NUL")).redirectErrorStream(true)
like image 51
dave_thompson_085 Avatar answered Jan 06 '23 22:01

dave_thompson_085