Environment Variables
Named values inherited by every child process, used to configure how the shell and other programs behave - distinct from ordinary shell variables, which don't get inherited.
A shell variable only exists in the shell that created it. An environment variable is a shell variable that's been marked for export, meaning every child process the shell starts gets a copy of it. That one distinction explains most of the confusion around variables "not working" in a script or a program launched from the shell.
Shell variable vs. environment variable
MY_VAR="hello" # shell variable - visible only in this shell
echo "$MY_VAR" # hello
bash -c 'echo $MY_VAR' # (nothing - the child shell never saw it)
export MY_VAR="hello" # now it's an environment variable
bash -c 'echo $MY_VAR' # hello
export is the whole mechanism. Anything exported before a child process
starts is inherited by it; anything not exported is invisible outside the
shell that set it. This is one-directional - a child process can't set an
environment variable that its parent shell will see afterward, since the
child only ever has its own copy.
Variables you'll actually use
| Variable | Purpose |
|---|---|
PATH |
Colon-separated directories searched, in order, for executables |
HOME |
The current user's home directory |
USER |
The current username |
SHELL |
The user's default login shell |
EDITOR |
The editor invoked by tools like crontab -e, git commit |
LANG / LC_* |
Locale settings - affects sorting, date formats, error message language |
Inspecting the environment
printenv PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
env | sort
lists every exported variable a process would inherit. printenv and env
with no arguments do almost the same thing; env can also run a command
with a modified environment (env VAR=value command), which is handy for
a one-off override without polluting the current shell.
Setting variables permanently
Where to put an export line depends on scope:
~/.bashrc- for variables needed in every interactive shell (most terminal tabs you open)~/.profileor~/.bash_profile- for variables needed at login, including in graphical sessions that don't necessarily read.bashrc/etc/environment- system-wide, applied at login for all users; unlike the files above, this one isKEY=valuepairs only, not a shell script, so noexportkeyword and no command substitution- A
.envfile loaded by a specific application ordocker compose- scoped to that tool, not the shell at large
After editing ~/.bashrc, reload it in the current shell with
source ~/.bashrc rather than opening a new terminal every time - see
Bash Basics.
Extending PATH instead of replacing it
A common mistake is overwriting PATH instead of adding to it:
export PATH="$HOME/bin:$PATH" # correct: prepend, keep the rest
export PATH="$HOME/bin" # wrong: every other command now "not found"
Using variables in scripts
Environment variables are how scripts read configuration without hardcoding
it - see Shell Scripting for reading them safely
(including handling the case where one isn't set), and
Sudo and Privilege for why
sudo strips most environment variables by default rather than passing
your shell's environment through to a root-owned process.