Setting the environment for ProcessBuilder
environment-variables, java, processbuilder
Solution
You need to understand that environment variables are local to process contexts. A new process gets a copy of the parent's environment but each copy is independent. Changes in the parent don't affect existing children (only new ones) and changes in children don't affect the parent or new children of the parent.
In your case, the Java process creates child process and puts a modified `PATH` variable into the child's context. This doesn't affect the Java process. The child process isn't a shell, so it ignores the `PATH` variable. The process is created directly using OS services. Those look into the context of the Java process which contains the old `PATH` variable unless you change the environment in the shell before you start the Java process.
To fix your issue, you have two choices:
Examine the `PATH` variable in Java, split it into path elements and search for the executable manually. You can then invoke `ProcessBuilder` with the absolute path and put the new `PATH` into the child, so grandchildren will have the correct path.
Invoke a shell to start the child process. The shell will use it's path (which you can pass via the environment).
The second case works like this:
- You create an environment with the correct `PATH`.
- You start a shell process.
- You pass the command to run as argument to the shell (`"sh", "-c", "cmd args"` or `"cmd.exe", "/c", "cmd args"`)
- The shell will notice that it has to run a command
- It will look into it's environment (which you configured in step #1), find the modified `PATH` and run the correct command.
The drawback of the second case is that you have to properly escape and/or quote the arguments for the command (`args`), or spaces and other special characters will cause problems.
Problem
I have a strange problem setting the Linux environment from Java (1.6); specifically the "PATH" variable. In a nutshell, I have a pipeline for running native processes, which uses `java.lang.ProcessBuilder`. The user can optionally set the environment variables via a `HashMap` named `environment`: ``` ProcessBuilder pb = new ProcessBuilder(args); Map<String, String> env = pb.environment(); if (environment != null) env.putAll(environment); Process process = pb.start(); ``` The `env` variable gets set properly, if I dump it to the console, with a correct value for the PATH variable. However, running the process results in a thrown `Exception`: `java.io.IOException: error=2, No such file or directory` The same process runs fine with identical environment variables in the terminal shell. To test this, I ran Eclipse AFTER setting the environment in the terminal. In this case the `ProcessBuilder` process runs correctly. So what must be happening is that the `ProcessBuilder` is not using the environment I set for it, but the current System environment instead. I can't find any satisfactory answers to this problem online. Perhaps this is an OS-specific issue? Or something else I'm missing?