If I run the following in a terminal I get the expected 123
$ /bin/sh
$ FOO=123
$ echo $FOO
123
Now I try to do the following with Java's 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());
I expect to see 123
but instead I get $FOO
.
What am I missing?
The following works under Windows.
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);
}
What am I missing?
Firstly,
$ FOO=123
sets a shell variable. It is local to the shell. If you want a variable to be in the environment that child processes see, you must export
it.
$ export FOO=123
But that's not the problem.
The real issue is the command string "echo $FOO"
. The problem is that $FOO
is shell syntax.... but when you run a command from Java using exec
:
exec
itself doesn't understand shell syntax, and exec
doesn't run the command in a shell. So the parameter that is given to the echo
command consists of the literal string $FOO
... and that is what it outputs.
There are three approaches to solving this:
Interpolate the variable in Java; eg
String[] cmd = {"echo", "123"}; Process p = Runtime.getRuntime().exec(cmd);
or by doing repeated search / replace for things that look like variables. (But this only deals with environment variable interpolation, not other forms of shell substitution.)
Assuming that you are doing something more complicated than echo
, write the command that you are running to do its own interpolation of environment variables. (This is clunky...)
Explicitly invoke the command in a shell; eg
String[] envp = {"FOO=123"}; String[] cmd = {"/bin/sh", "-c", "echo $FOO"}; Process p = Runtime.getRuntime().exec(cmd, envp);
Note that you can use any shell, and provide pretty much any shell-ism that can be expressed in a single shell command line.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.