我想在从java代码执行脚本之前加载我在.bashrc文件中定义的变量。该脚本通过ProcessBuilder执行。在网络上,我看到命令数组应该以{{1}}开头,如下所示:
bash -c
确实,waitFor永远不会回来!如果我删除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");
}
,那么bash -c
将不为零,因为尚未加载变量。
请注意.bashrc中没有单个变量。我可以使用ProcessBuilder修复问题,还是有更好的选择?
答案 0 :(得分:5)
Bash
必须作为交互式shell 调用read and execute commands from ~/.bashrc
。运行bash -c command
时,您在非交互式shell中执行command
。要以交互方式运行(并阅读.bashrc
),只需添加-i
:
String[] cmdline = {"/bin/bash", "-ic", "python /home/mahmood/temp.py"};
另请注意,必须将命令字符串(python /path/to/file
)指定为单个单词(从shell调用时注意单引号):
bash -ic 'python /home/mahmood/temp.py'
或其他方式,bash
将执行python
(第一个单词)以交互方式(不运行脚本) - 这就是您waitFor
永远不会的原因回报。
由于运行交互式shell只是为了从.bashrc
加载一些环境变量可能是一种过度杀伤,你可以在一个单独的文件中提取感兴趣的变量,例如:
export var1=val1
export var2='val 2'
...
然后来源该文件只有才能运行您的python
脚本:
String[] cmdline = {"/bin/bash", "-c", ". /path/to/envfile; python /home/mahmood/temp.py"};
答案 1 :(得分:1)
另一种方法是手动添加环境变量作为ProcessBuilder
环境的一部分。
例如,假设我们已将所需的环境变量存储在字符串数组envVars
中,则以下代码段将环境变量添加为ProcessBuilder
环境的一部分:
ProcessBuilder pb = new ProcessBuilder(Arrays.asList("python", "temp.py"));
pb.directory(new File("/home/mahmood/"));
Map<String, String> env = pb.environment();
Map<String, String> envToReproduce = new HashMap<String, String>();
for(int x=0;x<envVars.length;x++){
System.out.println(envVars[x]);
String[] tempEnv = envVars[x].split("=");
if(tempEnv.length>1){
String envVal = tempEnv[1].replaceAll("'","");
envToReproduce.put(tempEnv[0], envVal);
env.put(tempEnv[0], envVal);
}
}