如果在终端中运行以下命令,则会得到预期的123
$ /bin/sh
$ FOO=123
$ echo $FOO
123
现在,我尝试使用Java的Runtime's exec()执行以下操作:
String[] envp = { "FOO=123" };
String cmd = "echo $FOO";
Process p = Runtime.getRuntime().exec(cmd, envp);
java.io.BufferedReader reader =
new java.io.BufferedReader(
new java.io.InputStreamReader(p.getInputStream()
)
);
System.out.println(reader.readLine());
我希望看到123
,但我却得到了$FOO
。
我想念的是什么?
String[] envp = { "FOO=123" };
String cmd = "cmd /c echo %FOO%";
Process p = Runtime.getRuntime().exec(cmd, envp);
p.waitFor();
java.io.BufferedReader reader =
new java.io.BufferedReader(
new java.io.InputStreamReader(p.getInputStream()
)
);
String line;
while((line = reader.readLine()) != null) {
System.out.println(line);
}
首先,
$ FOO=123
设置外壳变量。它是外壳程序的本地文件。如果要将变量置于子进程看到的环境中,则必须
export
它。$ export FOO=123
但是那不是问题。
真正的问题是命令字符串"echo $FOO"
。问题是$FOO
是shell语法....但是当您使用exec
从Java运行命令时:
exec
本身不理解shell语法,并且[
exec
不在外壳中运行命令。因此给 echo
命令提供的参数由文字字符串$FOO
...组成,这就是它的输出。有三种解决方法: 插入Java中的变量;例如
String[] cmd = {"echo", "123"}; Process p = Runtime.getRuntime().exec(cmd);
或通过重复搜索/替换看起来像变量的东西。 (但这仅处理环境变量插值,而不处理其他形式的外壳替换。)
假设您要执行的操作比
echo
更复杂,请编写您要运行的命令以对其环境变量进行内插。 (这很笨拙...)在外壳中明确调用命令;例如
String[] envp = {"FOO=123"}; String[] cmd = {"/bin/sh", "-c", "echo $FOO"}; Process p = Runtime.getRuntime().exec(cmd, envp);
请注意,您可以使用任何外壳程序,并且几乎可以提供任何可以在单个外壳程序命令行中表达的外壳程序。