I am currently using ProcessBuilder to run commands from a java server. This server is to replace an old Perl server, and a lot of our legacy code specifies platform specific command lines.
For instance, on windows it might do:
command -option "hello world"
and on unix it might do:
command -option 'hello world'
The problem is that ProcessBuilder and Runtime.exec both take in tokenized command lines (e.g., {"command", "-option", "hello world"} for both unix and windows).
While I prefer the platform independant way, we have somewhere in the range of 30 million lines of perl code in our codebase. Without me writing a tokenizer for the different platforms (not a big deal really, I just don't want to make a WTF), is there a way to let the shell on the operating system tokenize the command line?
Are you able to use the overloaded Runtime.exec(String) that takes a single String and runs that as the entire command?
The following works for me on Windows:
Process p = Runtime.getRuntime().exec("perl -e \"print 5\"");
System.out.println(IOUtils.toString(p.getInputStream()));
p.destroy();
This is more or less what Runtime.exec(String) is doing:
public static void main(String [] args) throws Exception {
Process p = new ProcessBuilder(getCommand("perl -e \"print 5\"")).start();
System.out.println(IOUtils.toString(p.getInputStream()));
p.destroy();
}
private static String[] getCommand(String input) {
StringTokenizer tokenizer = new StringTokenizer(input);
String[] result = new String[tokenizer.countTokens()];
for (int i = 0; tokenizer.hasMoreTokens(); i++) {
result[i] = tokenizer.nextToken();
}
return result;
}
I think the quotes are being interpreted by the shell. Instead, put the command in a shell script:
$ cat temp.sh
#!/bin/sh
perl -e "print 5"
and execute it:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class PBTest {
public static void main(String[] args) {
ProcessBuilder pb = new ProcessBuilder("./temp.sh");
pb.redirectErrorStream(true);
try {
Process p = pb.start();
String s;
BufferedReader stdout = new BufferedReader (
new InputStreamReader(p.getInputStream()));
while ((s = stdout.readLine()) != null) {
System.out.println(s);
}
System.out.println("Exit value: " + p.waitFor());
p.getInputStream().close();
p.getOutputStream().close();
p.getErrorStream().close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Console:
5
Exit value: 0