Java 使用processbuilder加载所有环境变量
我想在从java代码执行脚本之前加载在.bashrc文件中定义的变量。该脚本通过ProcessBuilder执行。在web上,我看到命令数组应该以Java 使用processbuilder加载所有环境变量,java,bash,processbuilder,Java,Bash,Processbuilder,我想在从java代码执行脚本之前加载在.bashrc文件中定义的变量。该脚本通过ProcessBuilder执行。在web上,我看到命令数组应该以bash-c启动,如下所示: String[] cmdline = {"/bin/bash", "-c", "python", "/home/mahmood/temp.py"}; final ProcessBuilder pb = new ProcessBuilder(cmdline); pb.command(cmdline); pb.redirect
bash-c
启动,如下所示:
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
,那么exitCode
将非零,因为变量尚未加载
请注意,.bashrc中没有一个变量。我可以用ProcessBuilder解决这个问题吗?或者有更好的选择吗?另一种方法是手动添加环境变量,作为
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);
}
}
ProcessBuilder pb=newprocessbuilder(Arrays.asList(“python”、“temp.py”);
pb.directory(新文件(“/home/mahmood/”);
Map env=pb.environment();
Map envroreproduct=new HashMap();
对于(int x=0;x1){
字符串enval=tempEnv[1]。replaceAll(“,”);
envroreproduct.put(tempEnv[0],envVal);
环境put(临时环境[0],环境值);
}
}
Bash
必须作为交互式shell调用,以执行以下操作。当运行bash-c命令时,您正在非交互式shell中执行command
。要以交互方式运行(并读取.bashrc
),只需添加-i
:
String[] cmdline = {"/bin/bash", "-ic", "python /home/mahmood/temp.py"};
另外,请注意,命令字符串(python/path/to/file
)必须指定为单个单词(从shell调用时请注意单引号):
否则,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"};
我看到pb.environment()
返回的内容与我的bashrc不同。我正在用Netbeans进行调试,所以我认为当Netbeans执行时,它不会读取bashrc,因此用户定义的变量被忽略。这意味着,使用Netbeans比我想象的要困难得多!为了测试提出的想法,我必须从终端运行和调试。谢谢。虽然第一个方法运行了脚本,但我看到在执行了pb.start()
之后,这些行被打印在输出窗口bash:cannotset-set-process-group(1615):设备的ioctl不合适
和bash:no-job-control在此shell中
,使用-ic
和“-c”有什么区别。“source~/.bashrc;python…”
?您看到这条消息是因为您运行Bash作为,但没有连接终端(因为您从Java运行它)。InteractiveShell运行起来有点“重”(请参阅),这就是为什么第二种方法可能更可取的原因。在第二种方法中,Bash是在非交互模式下运行的,但在执行Python脚本之前,我们首先获取环境变量的源代码(-ic
与-i-c
的编写方法一样简单);python…“
(除了您没有使用第二个表达式运行交互式shell之外)是您的.bashrc
如果没有在交互式shell中运行,可能会过早退出—请检查.bashrc
的开头,并查找类似以下内容:[-z“$PS1”]&&return
。如果您修改.bashrc
使其在非交互式shell中源代码时不退出,例如仅保留env vars,那么您正在接近答案中的第二个方法。谢谢。事实上,我从这次问答中学到了很多关于壳牌的东西,但我现在还没有注意到!
String[] cmdline = {"/bin/bash", "-c", ". /path/to/envfile; python /home/mahmood/temp.py"};