I know that
VARIABLE=value creates an environment variable, and
export VARIABLE=value makes it available to processes created by the current shell.
env shows the current environment variables, but where do they live? What comprises an environment variable (or an environment, for that matter)?
I know that
An environment is not as magical as it might seem. The shell stores it in memory and passes to the
execve() system call. The child process inherits it as an array pointer called
environ. From the
#include <unistd.h> int execve(const char *filename, char *const argv, char *const envp);
argvis an array of argument strings passed to the new program.
By convention, the first of these strings should contain the filename associated with the file being executed.
envpis an array of strings, conventionally of the form key=value, which are passed as environment to the new program.
environ(7) manpage also offers some insight:
extern char **environ;
environpoints to an array of pointers to strings called the "environment". The last pointer in this array has the value
NULL. (This variable must be declared in the user program, but is declared in the header file
<unistd.h>in case the header files came from libc4 or libc5, and in case they came from glibc and _GNU_SOURCE was defined.) This array of strings is made available to the process by the exec(3) call that started the process.
Both of these GNU manpages match the POSIX specification
You've got it just a little wrong:
SOME_NAME=value creates a shell variable (in most shells).
export SOME_NAME=value creates an environment variable. For better for for worse, most Unix/Linux/*BSD shells use identical syntax in accessing environment variables and shell variables.
In some larger sense, an "environment" is just the information that goes along with program execution. In C programs, you might find the process ID with a
getpid() call, in a shell program you would use a variable access:
$$. The process ID is just part of the program's environment. I believe the term "environment" comes from some of the more theoretical computer science topics, like modelling program execution.. Models of program execution have an environment "which contains the associations between variables and their values".
And this latter, stronger definition is what an "environment" is for Unix/Linux/*BSD shells: an association between names ("variables") and their values. For most Unix-style shells, the values are all character strings, although that's not as strictly true as it used to be. Ksh, Zsh and Bash all have typed variables these days. Even shell function definitions can be exported.
The use of an environment separate from plain shell variables involves the
fork/exec method of starting a new process that all Unixes use. When you
export a name/value pair, that name/value pair will be present in the environment of new executables, started by the shell with an
execve(2) system call (usually following a
fork(2), except when the
exec shell command was used).
main() function of new binary has its command line arguments, the environment (stored as a NULL-terminated array of pointers to
var=value strings, see the
environ(7) man page). Other state that's inherited includes
ulimit settings, current working directory, and any open file descriptors that the
execve() caller didn't have FD_CLOEXEC set for. The current state of the tty (echo enabled, raw mode, etc.) could also be considered part of the execution state inherited by a newly-
bash manual's description of the execution environment for simple commands (other than builtin or shell functions).
Unix environment is different from at least some other operating systems: VMS "lexicals" could be changed by a child process, and that change was visible in the parent. A VMS
cd in a child process would affect the working directory of the parent. At least in some circumstances, and my memory may be failing me.
Some environment variables are well known,
$LD_LIBRARY_PATH and others. Some are conventional to a given programming system, so that a parent shell can pass lots and lots of special-purpose information to some program, like a specific temporary directory, or a user ID and password that don't show up in
ps -ef. Simple CGI programs inherit a lot of information from the web server via environment variables, for example.
Environment variables in their rawest form are just a set of name/value pairs. As described in the bash man page (
man 1 bash) under the ENVIRONMENT section:
When a program is invoked it is given an array of strings called the environment. This is a list of name-value pairs, of the form name=value. The shell provides several ways to manipulate the environment. On invocation, the shell scans its own environment and creates a parameter for each name found, automatically marking it for export to child pro- cesses. Executed commands inherit the environment.
In practical terms, it allows you to define behavior that is shared or unique to programs invoked from the present shell. For example, when using
visudo you can define the
EDITOR environment variable to define another editor other than the one your system would use by default. The same can be held true for things like the
man command which looks at your
PAGER environment to work out what pager program should be used to display the output of the man page with.
Quite a lot of unix commands read the environment and depending on what is set there alter their output/processing/action depending on these. Some are shared, some are unique to the program. Most man pages contain information on how the environment variable have an effect on the described program.
Other practical illustrations are for things such as systems with several installs of Oracle on the same platform. By setting
ORACLE_HOME, the whole suite of oracle commands (as loaded from your
PATH environment variable) then pull settings, definitions, mappings and libraries from under that top level directory. The same hold true for other programs such as java with it's
JAVA_HOME environment variable.
bash itself has many environment variables which can change the behavior of a range of things from history (
HISTFILE etc), screen size (
COLUMNS), tab completion (
GLOBIGNORE) locale and character encoding/decoding (
LC_*), prompt (
PS4), and so forth (again seek knowledge from the bash man page).
Also you can write scripts/programs that make use of your own custom environment variables (to pass settings, or change functionality).
"Environment Variables" are a set of dynamic named values that can affect the way running processes will behave on a computer.
They are part of the operating environment in which a process runs. For example, a running process can query the value of the TEMP environment variable to discover a suitable location to store temporary files, or the HOME or USERPROFILE variable to find the directory structure owned by the user running the process.
More info here → http://en.wikipedia.org/wiki/Environment_variable.
Everything you want to know about Environment Variables... ↑
This answer requires some shell scripting experience and knowledge with the terms variable, value, variable substitution, prompt, echo, kernel, shell, utility, session and process.
An environment variable (envar) is a set of global defined variables that can effect the way a given processes will behave on a computer's operating system.
1. An exemplary introduction:
We substitute envars with a
$ and capitalized letters. For example:
We can print an envar this way:
$PS1 holds the value of the Unix prompt. Say its native values are
\ustands for (current) user,
\wstands for working directory,
$is to border the prompt.
So, if we do:
echo $PS1, we see the values of
\w plus the dollar sign in the end.
We could change the Unix behavior in that context, if we change the values of that envar. For example:
Now the prompt looks like this (assuming the work directory is named "John"):
In the same manner we could do
PS1="Hello, I'm your prompt >", so
echo $PS1 will bring:
Hello, I'm your prompt >
In Bash 4.x.x, we can print ALL envars in the system with the
env command. I suggest executing
env in the terminal and take some look at the output.
2. How are these data shown and manipulated:
The terminal of a session let's us to customize the envars that are coming with Bash.
The aforementioned changes are usually temporary, and here's why:
Each session (which isn't a sub-session) is unique, and several processes can run uniquely at the same time (each with its own set of envars) but usually there is inheritance from session 0 to session 1 and upwards.
Changes we make to one process are unique to it, and will cease if we close it without saving them in some way.
So how can we save these changes:
There are several types of ways available to store envar changes, depending on the scope we pick. Here are different scopes (levels) for such changes:
- Process level: The envars are only available for programs in the current session.
- Export level: The envars are available for programs in the current session, or all its sub-sessions.
- Global level: The changes will be stored for all sessions whatsoever (primary and all subs).
Where are envar data stored:
Unix is built of 3 main layers: Kernel, shell, and utilities. AFAIK each shell has its own envars, and these are built primarily or exclusively in the shell.
The specific location in which to globally change these is usually
/etc/profile though we can also do that in
.bashrc of course.
3. Creating new envars:
We can create new envars and here is a way; as of Bash 4.x.x there is no native enavar named
MESSAGE (as said, envars are usually uppercased).
will create it for us, and now if we type echo
$MESSAGE, we get
If we'll execute
bash in our current working session (window), we would start a new bash sub-session and will no longer work in the original process, unless we execute
Note: In operating systems with a terminal emulator (like Ubuntu desktop), a sub-session usually runs on the same window, but a new session in another window isn't a sub-session of the existing one (it's an adjacent process).
Note: Don't use special signs in envar values such as ! or they won't be saved.
Exporting the envar from the original session to all sub-sessions:
We can still use the envar created in the first session, in the second one as well, without registering it in the user or global level conf files (see following data). Here's how to do that:
Go to the original session (whether on the current window or another) and execute:
when exporting, don't use a
It is now exported to all sub-sessions. If you'll do
echo $MESSAGE on a sub-session, whether from your user or another, it will then be printed.
Note that Shell internal variables such as
PS1 should not be exported, but if you do want to export them from whatever reason and they don't appear, don't execute
export, but rather
4. The $PATH envar:
$PATH is the envar that users will usually change the most.
echo $PATH, we are going to see this stream:
The printed values of this envar are separated by colons (:) there, but here's a potentially more comfortable way (these are the same values):
/usr/local/bin /usr/bin /bin /usr/local/games /usr/games
These are direcotries to search for, when we run a utility.
which echo we will get its file location - for example, we might see it exists in
Based on that we don't have to type echo envar to view the evnar's values. We can also do:
The envar will still be executed, for example:
/home/User || /root
/home/User || /root
$HOME is abbreviated as
The system-$PATH relations, and a possible user interaction:
In Bash 4.x.x, when we use a utility without its full path, the system will use all 6 values mentioned above, of the
$PATH envar. So, it will start from
/user/local/bin, and will follow all its content looking for the
In this case, it will stop at
/bin/echo, in which, in this case, the executable resides.
Hence, the main reason we might customize the
$PATH envar, is installing executables that are not under any of its native values.
After installing such executables, we should set their
$PATH value accordingly and then we would be able to work with them.
5. Appendix - expanding
export $PATH to bash sub-sessions (that includes bash extensions like WP-CLI for WordPress or Drush for Drupal ) this way:
This will add a new value
$PATH, and then right afterwards, it will annex any native values to it (right after the colon), which are stored under the syntax
Such permanent change can be done in the relevant script, usually under
/etc/profile and by the name