I want to load the variables I have defined in the .bashrc file prior to the execution of a script from a java code. The script is executed via the ProcessBuilder. On the web, I see that the command array should be started with bash -c
as below:
String[] cmdline = {"/bin/bash", "-c", "python", "/home/mahmood/temp.py"};
final ProcessBuilder pb = new ProcessBuilder(cmdline);
pb.command(cmdline);
pb.redirectOutput(Redirect.INHERIT);
final Process p = pb.start();
int exitCode = p.waitFor();
if (exitCode != 0) {
throw new IOException("... python failed :( \n");
}
Indeed the waitFor never returns! If I drop the bash -c
, then the exitCode
will be non-zero since the variables have not been loaded.
Please note that there is not a single variable in the .bashrc. Can I fix the problem with ProcessBuilder or there is a better option for that?
Bash
has to be invoked as an interactive shell to read and execute commands from ~/.bashrc
. When running bash -c command
you're executing command
in a non-interactive shell. To run interactively (and read .bashrc
), just add -i
:
String[] cmdline = {"/bin/bash", "-ic", "python /home/mahmood/temp.py"};
Also, note that the command string (python /path/to/file
) has to be specified as a single word (notice single quotes when invoked from shell):
bash -ic 'python /home/mahmood/temp.py'
or otherwise, bash
will execute python
(the first word) interactively (not running the script) -- and that's the reason your waitFor
never returns.
Since running an interactive shell just to load some environment variables from .bashrc
might be an overkill, you could extract the variables of interest in a separate file, for example:
export var1=val1
export var2='val 2'
...
and then source that file just before running your python
script:
String[] cmdline = {"/bin/bash", "-c", ". /path/to/envfile; python /home/mahmood/temp.py"};