我目前正在使用ProcessBuilder从java服务器运行命令。此服务器将替换旧的Perl服务器,并且我们的许多遗留代码指定了特定于平台的命令行。
例如,在Windows上可能会这样做:
command -option "hello world"
并且在unix上可能会这样做:
command -option 'hello world'
问题是ProcessBuilder和Runtime.exec都为unix和windows接受了标记化的命令行(例如,{“command”,“ - option”,“hello world”})。
虽然我更喜欢平台独立的方式,但我们的代码库中有大约3000万行perl代码。如果没有我为不同的平台编写一个标记器(真的不是很重要,我只是不想制作WTF),有没有办法让操作系统上的shell标记命令行?
答案 0 :(得分:7)
您是否能够使用带有单个String的重载Runtime.exec(String)并将其作为整个命令运行?
以下适用于Windows:
Process p = Runtime.getRuntime().exec("perl -e \"print 5\"");
System.out.println(IOUtils.toString(p.getInputStream()));
p.destroy();
这或多或少是Runtime.exec(String)正在做的事情:
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;
}
答案 1 :(得分:5)
我认为引用是由shell解释的。相反,将命令放在shell脚本中:
$ cat temp.sh
#!/bin/sh
perl -e "print 5"
并执行它:
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();
}
}
}
控制台:
5
Exit value: 0