0

I need to set an environment variable during runtime and fetch the value of that variable in UNIX environement using JAVA . Given below is my code.But, it's not able to fetch the environment variable and process output is not getting shown in the console. No exeception is thrown.

public static void main (String[] args) { String USR_HOME = System.getProperty("user.home"); String profileName = USR_HOME+"/.profile"; String installPath = System.getProperty("user.dir"); String str = ""; try { PrintWriter dynServ = new PrintWriter(new BufferedWriter(new FileWriter(profileName,true))); str = "FIC_HOME=" + installPath; dynServ.println(str); str = "export FIC_HOME"; dynServ.println(str); dynServ.flush(); dynServ.close(); }catch (Exception e){ System.out.println(e.getMessage()); } ProcessBuilder pb = new ProcessBuilder("sh","-c",". ./.profile"); Map<String, String> env = pb.environment(); env.put("FIC_HOME", USR_HOME+"/Path"); pb.directory(new File(USR_HOME)); try { Process p = pb.start(); BufferedReader Inreader = new BufferedReader(new InputStreamReader(p.getInputStream())); String line=""; while ((line=Inreader.readLine())!=null) { System.out.println(line); //System.err.println(line); } } catch (Exception ex) { System.out.println("Exeception ::: "+ex.getMessage()); } System.out.println("FIC_HOME value :::"+System.getenv("FIC_HOME")); 

Output is: .profile executed FIC_HOME value :::null

Can anyone suggest something ??

6 Answers 6

3

The current java process' environment does not get modified by child processes run from it. Your Runtime.exec creates a child process, which is having its own environment (initialized fom the environment of the current java process). This child process is running for a short time and afterwards terminates. This however did not change the environment of the current java (i.e. parent) process at all -- that's why System.getenv on the parent process still has no value for the env var.

Sign up to request clarification or add additional context in comments.

Comments

2

I don't know java but as far as I see you are executing all the commands from inside a child shell of your java program (String[] command = {"sh", "-c", "cd" , ". ./.profile" };). That means that the environment variable is set inside this sh shell and exported to its childs. But the parent (the java program) doesn't see this variable.

Comments

0

Well, it is not clear why your program needs to define an environment variable in the .profile file. If you clarify what you actually want to accomplish perhaps we could help more. You current approach does not sound like a good idea, because you will need to be very careful not to incorrectly override the .profile file if it already contains valuable information.

Now, there is a simple way to check if you are getting any errors using the error output stream of your process object.

You can also read the .profile file and see if its contents match those that you intended to write on it.

Your second chunk of code seems to simply run the .profile file where you just wrote the environment variable. I can only assume your .profile file only says:

FIC_HOME=/home/edalorzo/ export FIC_HOME 

So, when you run your code in your second process, I do not see why any particular output should be generated.

After writing the file, you could also check if your command is actually reading properly the .profile file.

The sh command says the following

The -c option causes the commands to be read from the string operand instead of from the standard input. Keep in mind that this option only accepts a single string as its argument, hence multi-word strings must be quoted.

So, chances are that you are using incorrectly the sh -c command.

Finally, as others have stated, the environment variables of your Java process is populated when the process starts. If you write new variables to the OS, Java will not realize of it.

You might like to take into consideration the process builder instead:

ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2"); Map<String, String> env = pb.environment(); env.put("VAR1", "myValue"); env.remove("OTHERVAR"); env.put("VAR2", env.get("VAR1") + "suffix"); pb.directory(new File("myDir")); Process p = pb.start(); 

This is a better approach to write environment variables into the current process.

1 Comment

I'm using one external API which requires FIC_HOME enc variable and can not this variable in .profile before executing my java code. So, I need to do this from my code only.My .profile has one echo statement.So, it should come in process inputstream.
0

Based on previous answers you can try to launch shell not as child shell but as continuation of parent one by command "source" or "."

Comments

0

Check the overloaded APIs for Runtime.exec. There are some which let you pass environment variables as an array, e.g. exec(String[] cmdarray, String[] envp)

That's how you set the variable into the environment of a child process. But as others have noted, it won't help you access an environment variable set in a child process in the parent process.

Your real requirement is unclear, but here's an example of passing environment variables to the child process and reading the variable (not setting the variable) back in the parent Java process.

Here is sample code:

import java.io.*; public class EnvTest { public static void main(String[] args) throws Exception { String[] cmd = {"sh","-c","env | grep FIC_HOME"}; String[] envp = {"FIC_HOME=foo"}; Process p = Runtime.getRuntime().exec(cmd, envp); BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); String line = null; while ((line = reader.readLine()) != null) { System.err.println(line); } } } 

And sample output:

$ java EnvTest FIC_HOME=foo 

Comments

0

@user709413 your (hacky) file-based approach will do the trick, but you need to use other file than .profile, cause it's loaded/read during user login. So pass the value to, e.g.: ${user.home}/your_app_name.store and.. read it in the other process.

However, I'd recommend to use other directory than user.home, cause it forces you to launch all processes by the same user and it might not be the case in the future. Try /opt for instance and make sure that other users will have read access to it.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.