Search code examples
javalinuxprocessenvironment-variablesprocessbuilder

Java processbuilder and using environment variables


What I want to do is I want to run a process, however because this process itself relies on environment variables, directly calling it causes error within the process. For those who are wondering what this is, it's rake tool. For this reason I thought maybe it's better to use bash and using it through bash would eliminate the issue. However that doesn't seem to be the case.

Here is my code:

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);
        }
    }

I know it is environment related issue because the error that I am getting is described here cannot load such file -- bundler/setup (LoadError)

Further I checked processBuilder.environment() returns less environment variables than entering env. I went ahead and changed the osw.write() line and tried echo $GEM_HOME there, which doesn't print anything and if I do this on my OSs bash then I get the path, I also tried other common things like echo $SHELL and it prints the shell location in both Java code and in bash.

So my questions are:

1) Why is my operating system's environment variables are different than the ProcessBuilder.environment() method?

2) Does Process class consider using environment variables that were given out by ProcessBuilder.environment()? If so then how can we add the missing ones from the operating system's level?


Solution

  • 1) The varaibles you see in your java process are those inheritd from the process you started the java process from. I.e. If you launch it from a shell it should have the same variables as the shell had. You need to investigate which variables are actually set before launching your Java application and why the ones you expect are not set in that context.

    To answer part 2, yes, the process will be launched with the environment in ProcessBuilder.environment(). You can simply add things to the map returned by ProcessBuilder.environment(), that will extend the runtime environment:

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