Scenario
While executing a series of commands using the ProcessBuilder I noticed I am currently not able to set an environment variable such that it remains "known" after a set of commands has been executed.
Question
How do I recreate the effects* of the export TASKDDATA=/var/taskd command in a .jar file?
Attempt 0
ProcessBuilder environment variable in java Provides a way to set the environment variable for each specific command, but when I execute the .jar of that solution and check if the environment variable $u is still set after execution, I find it is not. Whereas $TASKDDATA does remain set after execution. To illustrate:
a#DESKTOP-desktopName:/mnt/e$ echo $TASKDDATA
a#DESKTOP-desktopName:/mnt/e$ TASKDDATA=/var/taskd
a#DESKTOP-desktopName:/mnt/e$ echo $TASKDDATA
/var/taskd
a#DESKTOP-desktopName:/mnt/e$ sudo java -jar autoInstallTaskwarrior.jar
[sudo] password for a:
Process ended with rc=0
Standard Output:
util/
Standard Error:
a#DESKTOP-desktopName:/mnt/e$ echo $TASKDDATA
/var/taskd
a#DESKTOP-desktopName:/mnt/e$ echo $u
Attempt 1
For a single command the environment variable can be using the solution I wrote in: Java ProcessBuilder how to get binary output from command. However that does not conserve the taskvariable for a second command in which it needs to be set again. However, when the export command is used, the environment variable is not required to be set again. Specifically this difference comes to light when the java code is finished and the user wants to enter any additional commands that require the environment variable. In that case, the user needs to first type the export command again.
Attempt 2
An additional difference occurs when a new shell is opened to acquire root priviliges with sudo -s. Not only does setting the environment within the .jar file require setting it again for every separate command but additionally the environment variable is not passsed along to the new shell with root priviliges. For example executing the following commands:
commandLines[53] = new String[4];
commandLines[53][0] = "sudo";
commandLines[53][1] = "-s";
commandLines[53][2] = "taskdctl";
commandLines[53][3] = "start";
commands[53].setCommandLines(commandLines[53]);
commands[53].setEnvVarContent("/var/taskd");
commands[53].setEnvVarName("TASKDDATA");
commands[53].setWorkingPath("/usr/share/taskd/pki");
commandLines[54] = new String[5];
commandLines[54][0] = "sudo";
commandLines[54][1] = "-s";
commandLines[54][2] = "task";
commandLines[54][3] = "sync";
commandLines[54][4] = "init";
commands[54].setCommandLines(commandLines[54]);
commands[54].setEnvVarContent("/var/taskd");
commands[54].setEnvVarName("TASKDDATA");
commands[54].setWorkingPath("/usr/share/taskd/pki");
returns:
53RUNNINGCOMMAND=sudo -s taskdctl start
The TASKDDATA variable must be set.
54RUNNINGCOMMAND=sudo -s task sync
Could not connect to 0.0.0.0 53589
Sync failed. Could not connect to the Taskserver.
Syncing with 0.0.0.0:53589
Note 1
Setting the environment variable $TASKDDATA=/var/taskd before executing the .jar with: TASKDDATA=/var/taskd sudo java -jar autoInstallTaskwarrior.jar does not ensure the environment variable $TASKDDATA remains available after the execution of the .jar file. Furthermore it is beyond the scope of the question as it is not set within the .jar file but outside the .jar file.
Note 2
I understood it is not appropriate to use the export command as a command that is executed by the processbuilder, much like the cd command.
*That is why the question focuses on reproducing the "longterm/lasting" effect/availability of setting the environment variable, rather than "how to execute the export command.".
when I execute the .jar of that solution and check if the environment variable $u is still set after execution, I find it is not.
That is the expected behavior. Some operating systems support the concept of global "environment" variables. But not UNIX. In UNIX like operating systems every process has its own private copy of environment vars. A process cannot modify the environment of another process. This is also why changing the current working directory in a process does not change the cwd of its parent process. Each process has its own cwd.
The usual way to workaround that limitation is for the child process to write the var=val pairs to stdout and the parent shell then evaluates that output to set the vars in its environment. For illustration assume the command is the following shell script, named myscript.sh, rather than a Java program:
#!/bin/sh
echo VAR_A=val_a
echo VAR_B=val_b
Then the parent shell does
export $(./myscript.sh)
Related
I am setting environment variable in my machine using export MY_KEY=foo. And I am trying to fetch it in JVM using System.getenv("MY_KEY"). This returns null. But running echo $MY_KEY shows foo on the terminal.
I have tried restarting the IDE. Doesn't work, still.
The environment variable is only available to sub processes of the shell that exported it. Did you start your IDE from that shell?
If you want the variable to be available all the time, you need to add it
to the /etc/profile file or create a extra file in /etc/profile.d. It depends on your operating system.
Upon logging into my CentOS 7 VM, my $JAVA_HOME is always set to :
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/jre, which is incorrect.
My ~/.bash_profile reads:
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.144-0.b01.el7_4.x86_64/jre
export JAVA_HOME
PYCHARM_HOME=/opt/pycharm-community-2017.2.3/
export PYCHARM_HOME
ECLIPSE_HOME=/opt/eclipse
export ECLIPSE_HOME
export SPARK_HOME=/opt/spark
PATH=$PATH:$HOME/.local/bin:$HOME/bin:$JAVA_HOME/bin:$SPARK_HOME/bin:$PYCHARM_HOME/bin:$ECLIPSE_HOME
export PATH
Sourcing .bash_profile each time I open a new terminal appears to correct the issue, but why is my $JAVA_HOME path defaulting to an old version on startup and not being set to the directory specified in .bash_profile?
Sourcing .bash_profile each time I open a new terminal appears to
correct the issue, but why is my $JAVA_HOME path defaulting to an old
version on startup and not being set to the directory specified in
.bash_profile?
You need to logout from current user and login again so environment variables changes take place.
May be useful
In Bash:
Bash as login shell will load /etc/profile, ~/.bash_profile, ~/.bash_login, ~/.profile in the order.
Bash as non-login interactive shell will load ~/.bashrc
Environment :
Use /etc/environment to permanently system wide (all users, all processes) set environmental variables for all users.
/etc/environment is a system-wide configuration file, which means it is used by all users. It is owned by root though, so you need to be an admin user and use sudo to modify it.
Suppose if you set foo="bar" variable foo will be accessible from all the user sessions. To test the variable output first source it
source /etc/environment
~/.profile is one of your own user's personal shell initialization scripts. Every user has one and can edit their file without affecting others.
/etc/profile and /etc/profile.d/*.sh are the global initialization scripts that are equivalent to ~/.profile for each user. The global scripts get executed before the user-specific scripts though; and the main /etc/profile executes all the *.sh scripts in /etc/profile.d/ just before it exits.
Also note,
The /etc/environment file sets the variable system wide for every user on login.
Commands in the bash_profile are is executed if the bash shell is opened by any user. So the variables would not be set unless a bash shell is opened at least one time.
Run ps in the interactive shell to make sure you're in bash.
Try bash -l after login and see if it fixes your problem.
Add set -x before JAVA_HOME=... to check if there's something wrong.
It worked for me!
In my case, The follwing caused the error:
export JAVA_HOME = /Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home
The error was that there were spaces before and after the = . The error disappeared after those spaces were removed.
So the correct command is as follows:
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home
There's an issue when I run the android Runtime.getRuntime().exec method.
I have a native binary file to be run on android and I start it with the java method Runtime.getRuntime().exec. But running this native binary file requires the addition of an environment variable. So I execute this command:
envSetCmd = {"sh", "-c", "export LD_LIBRARY_PATH="+excBinFilepath+":$LD_LIBRARY_PATH"}.
It doesn't work when I check the environment variable with the command:
sh, -c, echo $LD_LIBRARY_PATH.
I think the reason is that when I set the environment variables I start a shell and when I check it with the command "echo" another shell was started. So the environment variables didn't work in the shell I check it.
I think there are two ways to solve this issue. The one is that running two commands in one shell. So I tried to use the command:
{"sh", "-c", "export LD_LIBRARY_PATH="+excBinFilepath+":$LD_LIBRARY_PATH", "-c", "echo $LD_LIBRARY_PATH"}.
Unfortunately it is illegal. The other is that I add the environment variables to the android user startup files. I tried to echo the $PATH, and I see the /system/bin/ and other path was loaded at the startup of android.
So I think there must be a file just like the ~/.bashrc in linux which could set the users' environment.
Any one could give me some clues about the ways I listed above? By the way, I shouldn't root the phone!
try to execute whatever you need to execute with env:
{"env", "LD_LIBRARY_PATH="+excBinFilepath, "yourCmd"}
I've tried to make a python script to switch between 32bit and 64 bit java but for some reason
os.system('export JAVA_HOME=/usr/java/path')
os.system('export PATH=$JAVA_HOME/bin:$PATH')
does nothing, but manually it works. How can I fix this? (BTW, this is running on a Linux system.)
The export line will set an environment variable for the shell in which it's executed and all its sub-shells. But what's happening here is that Python creates a new shell, executes the line to set the environment variable, and then the shell terminates. That means the environment variable is no longer in force. In fact, the JAVA_HOME environment variable you set in the first line isn't even in force for the second line when that gets executed, because that's in its own shell that also terminates immediately!
The way round it is to run a whole shell script that sets the environment variable and then launches Java:
#!/bin/bash
JAVA_HOME=/usr/java/path
PATH=$JAVA_HOME/bin:$PATH
java ...
Environment variables are local to each process. If you want to make a permanent change then you can follow the official java PATH instructions. They recommend adding the export variable command to your .bashrc file.
In ~/.bashrc:
export JAVA_HOME=/usr/java/path
export PATH=$JAVA_HOME/bin:$PATH
You can chain the commands together - jdk set + script execution like this:
setJdk4Gradle = 'export JAVA_HOME=/home/jdkPath && export PATH=$JAVA_HOME/bin:$PATH'
os.system(setJdk4Gradle + ' && executeSomething')
I followed all the steps on pig.apache.org ,but not able to remove this error by setting java variable. I set the variable earlier while installing java jdk but its asking again for the variable.
You need to understand how environment variables work in Linux (or Windows).
The chances are that you only set JAVA_HOME temporarily in the shell that you used to do the installation. To set JAVA_HOME permanently (on Linux / UNIX) you need to set it in a shell "rc" file that gets run each time a new shell is created. (It depends on which shell you are using, but man can tell you about that ...)
if you are installing PIG on ubuntu do this
open bashrc file using below command and and lines to the end of the file
vi ~/.bashrc
export JAVA_HOME=/usr/lib/jvm/java-1.6.0-openjdk-i386
then log out or Restart your system and try again.
For CentOS
Create a new file called java.sh
vim /etc/profile.d/java.sh
Within this file, initialize the necessary environment variables
export JRE_HOME=/usr/java/jdk1.5.0_12/jre
export PATH=$PATH:$JRE_HOME/bin
export JAVA_HOME=/usr/java/jdk1.5.0_12
export JAVA_PATH=$JAVA_HOME
export PATH=$PATH:$JAVA_HOME/bin
Replace java path with your java installation.
Source
To set your JAVA_HOME variable for your current shell, use the export command. This will immediately create an environment variable for JAVA_HOME, but the variable is lost when your shell is closed.
export JAVA_HOME=<path_to_java_sdk>
The best way to set the JAVA_HOME environment variable for Pig and Hadoop use is by adding it to your local rc file. The reason for this is that some distributions of Hadoop (Cloudera, Hortonworks, MapR) may include their own Java installation for the Hadoop application itself. You may not want to create a global environment variable, since it may interfere with Hadoop/Hive/etc.
To have the variable set for individual Hadoop/Pig users on the server, they need to run the following command:
echo "export JAVA_HOME=<path_to_java_sdk>" >> ~/.bashrc
Afterward executing the command, they can source ~/.bashrc to instantiate the environment variable.