我在使用processbuider添加进程环境的路径时遇到问题。我不知道为什么这个过程忽略了环境。这是我的例子:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Map;
public class main {
public static void main(String [ ] args) {
try {
String s = null;
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", "fsl");
Map<String, String> env;
env = pb.environment();
env.put("FSLDIR", "/usr/local/fsl/bin/");
Process p = pb.start();
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
System.out.println("Process p:");
// read the output from the command
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
//////////*********\\\\\\\\\\\
ProcessBuilder pb2 = new ProcessBuilder("/usr/local/fsl/bin/fsl");
s = null;
Process p2 = pb2.start();
stdInput = new BufferedReader(new
InputStreamReader(p2.getInputStream()));
stdError = new BufferedReader(new
InputStreamReader(p2.getErrorStream()));
System.out.println("Process p2:");
// read the output from the command
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出:
Process p:
/bin/bash: fsl: command not found
Process p2:
DISPLAY is not set. Please set your DISPLAY environment variable!
你看到FSL想要设置更多的变量。这就是为什么p2不是一个选项。
答案 0 :(得分:1)
正如Jdamian所说,Bash搜索PATH
environment variable中的目录以查找二进制文件--Bash不会查找您的FSLDIR
变量,也不会将任意变量的值视为可执行文件。
在遇到流程库问题时(例如,Java中的ProcessBuilder
,Python中的subprocess
),您应该始终做的第一件事就是尝试直接在shell中复制问题。如果您在shell中运行fsl
或/bin/bash -c fsl
,您可能会看到相同的错误(如果您没有以与shell相同的方式运行Java二进制文件),这会确认问题与Java无关。
一旦你确认这只是一个如何修复它的问题。如果您希望fsl
始终可用,请将其包含的目录添加到~/.bashrc
文件中的PATH中:
export PATH="$PATH:/usr/local/fsl/bin"
如果您只想在Java二进制文件中使用它,请修改进程中的PATH
:
// notice there's no need for `bash -c`
ProcessBuilder pb = new ProcessBuilder("fsl");
pb.environment().put("PATH",
"/usr/local/fsl/bin" + File.pathSeparator + System.getenv("PATH"));
然而,在实践中,如果不修改PATH
而只是总是通过绝对路径调用外部进程,那么代码通常会更易于维护和使用,就像第二个例子一样:< / p>
ProcessBuilder pb = new ProcessBuilder("/usr/local/fsl/bin/fsl");
这两个命令(大致)是等价的,但后者更清晰,不太可能引入混乱的错误。