Java ProcessBuilder和使用环境变量

4

我想要做的是运行一个进程,但因为这个进程依赖于环境变量,直接调用会导致进程内部发生错误。对于那些不知道它是什么的人来说,它是rake工具。因此,我认为使用bash可能更好,并且通过bash使用可以消除问题。 然而,事实并非如此。

以下是我的代码:

public static void runPB(String directory) throws IOException {
        ProcessBuilder processBuilder = new ProcessBuilder(
                "/bin/bash");
        processBuilder.directory(new File(directory));
        Process process = processBuilder.start();
        OutputStreamWriter osw = new OutputStreamWriter(process.getOutputStream());
        osw.write("rake routes");
        osw.close();
        printStream(process.getErrorStream());
        printStream(process.getInputStream());
    }

    public static void printStream(InputStream is) throws IOException {
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        String line;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
    }

我知道这是一个与环境相关的问题,因为我在这里描述了错误cannot load such file -- bundler/setup (LoadError)
此外,我检查了processBuilder.environment()返回的环境变量比输入的env要少。我继续更改了osw.write()行并尝试在那里使用echo $GEM_HOME,但没有输出任何内容。如果我在我的操作系统的bash上执行此操作,则会输出路径。我还尝试了其他常见的事情,如echo $SHELL,并且在Java代码和bash中都打印出了shell位置。
所以我的问题是:
1)为什么我的操作系统环境变量与ProcessBuilder.environment()方法不同?
2)Process类是否考虑使用由ProcessBuilder.environment()提供的环境变量?如果是,那么我们如何添加缺少的操作系统级别的环境变量?

1
你在启动Java进程之前是否已经设置了这些环境变量?如果没有,那么ProcessBuilder可能会返回不同的值。环境变量是进程特定的,并且从父(执行)进程继承。请参阅man 2 execve - JiriS
1个回答

6

1) 在 Java 进程中看到的变量是从启动 Java 进程的进程继承而来的。例如,如果您从 shell 启动 Java 进程,则它应具有与 shell 相同的变量。您需要调查在启动 Java 应用程序之前实际设置了哪些变量,以及为什么您期望的变量在该上下文中未设置。

对于第二部分,是的,进程将使用 ProcessBuilder.environment() 中的环境启动。您可以简单地将内容添加到 ProcessBuilder.environment() 返回的映射中,这将扩展运行时环境:

ProcessBuilder pb = new ProcessBuilder("foo");
pb.environment().put("MY_VAR", "foobar");

非常感谢!当我构建JAR时,它像魔法一样工作。然后我使用bash来使用我的IDE,它也可以工作。 - Sarp Kaya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接