Starting external processes in Java

Wednesday, September 9th, 2009

This is mainly for my own reference in the future but thought that I would post it here as well as I couldn’t really find anything on this while looking it up.

Launching an external process in Java is done through the ProcessBuilder class. Runtime.exec can be used as well but this just calls ProcessBuilder itself.

The constructor for ProcessBuilder takes a String vararg of the executable and the arguments. There is also the method ProcessBuilder.directory(File directory) to set the directory the process is launched from. ProcessBuilder.start() starts the process and then returns a Process object for the process.

ProcessBuilder builder =

   new ProcessBuilder("exe", "arg 1", "arg 2", "arg 3");

builder.directory(new File("/path/to/working/dir"));

Process process = builder.start();

The part that I found the be awkward is the way that arguments are handled. You have to have 1 element per argument, as in the example above, having spaces doesn’t matter, the program will still treat it as one argument. Passing it as “\”arg 1\”" is unnecessary, the program will receive it as “arg 1″ with speech marks included. The example where I was having problems involved start ksh and getting it to run a program and pipe that into another. From command line it was:

ksh -c “exec arg | tee exec.log”

However, to run this from ProcessBuilder I needed

ProcessBuilder builder =

   new ProcessBuilder("ksh", "-c", "exec arg | tee exec.log");

Where the value of the -c parameter was passed as one argument. Some things I tried that didn’t work were:

ProcessBuilder builder =

   new ProcessBuilder("ksh", "-c", "\"exec arg | tee exec.log\"");

 

ProcessBuilder builder =

   new ProcessBuilder("ksh", "-c", "exec", "arg", "|", "tee", "exec.log");

 

ProcessBuilder builder =

   new ProcessBuilder("ksh", "-c exec arg | tee exec.log");

There were a few others as well. The problem is that with the first one of them, ksh would execute “exec arg | tee exec.log” including the speech marks so it wouldn’t find it, just as if you had typed that into a terminal. The second one, ksh would execute exec but then arg would be passed as an argument to ksh rather than exec and the same for all the others after it. The final one, ksh would receive the whole thing as single argument and so wouldn’t recognize it as it is expecting [-c] [command] as 2 arguments rather than one.

Tags: ,