Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Evaluation of environment variables in command run by Java's Runtime.exec()

I have a scenarios where I have a Java "agent" that runs on a couple of platforms (specifically Windows, Solaris & AIX). I'd like to factor out the differences in filesystem structure by using environment variables in the command line I execute.

As far as I can tell there is no way to get the Runtime.exec() method to resolve/evaluate any environment variables referenced in the command String (or array of Strings).

I know that if push comes to shove I can write some code to pre-process the command String(s) and resolve enviroment variables by hand (using getEnv() etc). However I'm wondering if there is a smarter way to do this since I'm sure I'm not the only person wanting to do this and I'm sure there are pitfalls in "knocking up" my own implementation.

Your guidance and suggestions are most welcome.

edit: I would like to refer to environment variables in the command string using some consistent notation such as $VAR and/or %VAR%. Not fussed which.

edit: To be clear I'd like to be able to execute a command such as:

perl $SCRIPT_ROOT/somePerlScript.pl args

on Windows and Unix hosts using Runtime.exec(). I specify the command in config file that describes a list of jobs to run and it has to be able to work cross platform, hence my thought that an environment variable would be useful to factor out the filesystem differences (/home/username/scripts vs C:\foo\scripts). Hope that helps clarify it.

Thanks. Tom

like image 542
Tom Duckering Avatar asked Feb 27 '23 18:02

Tom Duckering


2 Answers

I think I misunderstood your question with my original answer. If you are trying to resolve environment variable references on the command lines that you generated from with-in Java, I think you may have to "roll your own".

There are many different standards for how these are expanded, depending on the operating system. In addition, this is typically a function of the shell, so even on the same OS there could be different ways. In fact, standard operating system process activation functions (e.g. exec in Unix) do not do command line expansion.

This is really not that difficult, with Java 5 and later. Define a standard for yourself, I typically use the Java standard that you see in security policy files and some enhanced property file definitions - ${var} expands to the variable/property name reference. Something like:

    private static String expandCommandLine(final String cmd) {
        final Pattern vars = Pattern.compile("[$]\\{(\\S+)\\}");
        final Matcher m = vars.matcher(cmd);

        final StringBuffer sb = new StringBuffer(cmd.length());
        int lastMatchEnd = 0;
        while (m.find()) {
            sb.append(cmd.substring(lastMatchEnd, m.start()));
            final String envVar = m.group(1);
            final String envVal = System.getenv(envVar);
            if (envVal == null)
                sb.append(cmd.substring(m.start(), m.end()));
            else
                sb.append(envVal);
            lastMatchEnd = m.end();
        }
        sb.append(cmd.substring(lastMatchEnd));

        return sb.toString();
    }
like image 157
Kevin Brock Avatar answered Mar 02 '23 07:03

Kevin Brock


Is there some reason system properties won't work? Use the -D flag on the command line, you can then retrieve it via System.getProperty

like image 26
Steve B. Avatar answered Mar 02 '23 07:03

Steve B.