The difference between "echo" and "export" an environment variable?
The environment is Ubuntu 18.
If I add one line JAVA_HOME="/usr/java11"
in /etc/environment, and execute source /etc/environment
, I can echo this environment variable:
echo $JAVA_HOME
/usr/java11
But if I try to get it from export, this variable is not in the list:
export | grep JAVA_HOME
--result is blank--
Then I use export $JAVA_HOME=/usr/java8
to export a variable (notice here is java8, not java 11), I can have:
export |grep JAVA_HOME
declare -x JAVA_HOME="/usr/java8"
Now, I can still echo $JAVA_HOME
as /usr/java11:
echo $JAVA_HOME
/usr/java11
Question: what is the difference of echo $variable
and export | grep JAVA_HOME
?
I try a simple python program, os.environ.get("JAVA_HOME")
returns "/usr/java8" from the export, not the echo.
Solution 1:
The issue here is not really the difference between echo
and export
, but rather the difference between an environment variable and a simple shell variable (and also about how the /etc/environment
file is normally used).
In particular, although /etc/environment
happens to contain lines of the form name=value
that are valid as POSIX shell variable assignments, its primary purpose (in a modern Linux system) is to be read by the pam_env
module during initialization of a user's session - it is pam_env
that exports them to the user's environment.
When you source /etc/environment
into your shell, there's no special magic that tells the shell that the assignments are those of environment variables (which are exported to the environment, and hence inherited by sub-processes) rather than regular shell variables (which are just available in the current shell scope).
Next time you log in, pam_env
will do its magic and JAVA_HOME
will then appear in the output of export | grep JAVA_HOME
.
See also
-
Difference between shell variables which are exported and those which are not in bash
-
What scopes can shell variables have?
Solution 2:
echo
and export
are very different commands in the first place.
-
echo
will display text. Inecho $JAVA_HOME
, the shell will substitute $JAVA_HOME with the contents of the shell variable JAVA_HOME it it is defined. Otherwise,$JAVA_HOME
will return an empty string. -
export
provides the "export" attribute to the shell variable.export JAVA_HOME
will set the export attribute, i.e., the variable will also be available in the environment of any sub shell or sub process rather than in your current shell only. If the variable is not yet set, you can define it while exporting as inexport JAVA_HOME=/usr/java11
.
In /etc/environment
, environment variables are registered with the syntax of a variable assignment. The content of /etc/environment
in a default Ubuntu install indeed can be executed. So if you execute the line you included:
`JAVA_HOME=/usr/java11`
Then, all that will do is assign the shell variable PATH the current value.
However, because you included the variable in /etc/environment
, it should be effectively be exported during the next startup of your system. Then, it should exist in export
and show up in echo $JAVA_HOME
in the first terminal you open. So what you currently observe is because you did not yet restart the machine after modifying /etc/environment
(and did not export the variable in other ways).