Question

I have the following windows batch file (run.bat):

@echo off
echo hello batch file to sysout

And the following java code, which runs the batch files and redirects output to a file:

public static void main(String[] args) throws IOException {
    System.out.println("Current java version is: " + System.getProperty("java.version"));

    ProcessBuilder pb =
            new ProcessBuilder("cmd.exe", "/c",
                    "run.bat"
                     ,">>", "stdout.txt","2>>", "stderr.txt"
                    );
    System.out.println("Command is: " + pb.command());

    Process proc = pb.start();

    InputStream in = proc.getInputStream();
    BufferedReader reader = new BufferedReader(new InputStreamReader(in));

    String line = null;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }

    int exitValue = proc.exitValue();
    System.out.println("Exit value: " + exitValue);
}

On JDKs up to and including JDK6u43 I get the following output:

Current java version is: 1.6.0_29
Command is: [cmd.exe, /c, run.bat, >>, stdout.txt, 2>>, stderr.txt]
Exit value: 0

and the script output is written to the file. As of JDK 6u45 and 7, I get the following output:

Current java version is: 1.6.0_45
Command is: [cmd.exe, /c, run.bat, >>, stdout.txt, 2>>, stderr.txt]
hello batch file to sysout
Exit value: 0

And nothing is written to the output file.

This may or may not be related to the changes made in Runtime.exec() , described at: http://www.oracle.com/technetwork/java/javase/6u45-relnotes-1932876.html

What is the correct way of starting a process on Windows with output redirected to files?

Note: In a real world scenario, the command to execute may include parameters with spaces, as in:

ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c",
"run.bat", "Some Input With Spaces", 
">>", "stdout.txt","2>>", "stderr.txt");
Was it helpful?

Solution 2

Several suggestions here:

  • Does the input with the spaces need to be treated as single String (with spaces),or id it in actual several inputs? If the first Option is the case I would suggest to quote it for the windows runtime:

ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", 
"run.bat", "\"Some Input With Spaces\"", 
">>", "stdout.txt","2>>", "stderr.txt");
  • Instead of redirecting the input to stdout.txt and stderr.txt using the shell, why not do it using Java using getOutputStream() and getErrorStream()? Here is an example using Guava's IO package. Of course you may want to have those in separate threads, you need proper exception handling, etc.

InputStream stdout = new BufferedInputStream(proc.getInputStream());
FileOutputStream stdoutFile = new FileOutputStream("stdout.txt");
ByteStreams.copy(stdout, stdoutFile);

InputStream stderr = new BufferedInputStream(proc.getErrorStream());
FileOutputStream stderrFile = new FileOutputStream("stderr.txt");
ByteStreams.copy(stderr, stderrFile);

stdout.close();
stderr.close();
stdoutFile.close();
stderrFile.close();
  • Another option, why not create a run.bat wrapper that will make the redirections?

@echo off
cmd.exe /c run.bat "%1" >> "%2" 2>> "%3"

OTHER TIPS

This is the simplest method i found on http://tamanmohamed.blogspot.in/2012/06/jdk7-processbuilder-and-how-redirecting.html

File output = new File("C:/PBExample/ProcessLog.txt");
ProcessBuilder pb = new ProcessBuilder("cmd");
pb.redirectOutput(output);

Use getOutputStream() on the process, instead of using System.out.println(). Sometimes the semantics change between Java implementations.

This seems to be a bugfix actually - the newer implementation makes sense.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top