systemd: Environment= / EnvironmentFile= ; cron: inside the script
Overview
Environment variables configure program behavior. The most important is
PATH (where to look for executables).
bash
echo $PATH # where commands are looked up
env # all environment variables
printenv HOME # one variable
echo "$HOME $USER $SHELL" # common ones
Options
bash
export VAR=value # for the current shell and CHILD processes
VAR=value command # for one command only
unset VAR # remove it
export PATH="$PATH:/opt/bin" # append a directory to PATH
export PATH="/opt/bin:$PATH" # ...prepend it (higher priority)
set # ALL shell variables (including non-exported)
The difference: a variable without export is visible only to the current
shell; with export, it's inherited by processes started from it.
Recipes
1
Where to save it (login vs. non-login)
File
When it's read
~/.bashrc
interactive non-login shells (a new terminal/tab)
~/.profile / ~/.bash_profile
login shells (SSH login/console login)
/etc/profile, /etc/profile.d/*.sh
system-wide for login shells
/etc/environment
system-wide for everyone (plain KEY=value, no export)
A subtlety: an SSH login is a login shell (reads ~/.profile), while a new
terminal in an already-open session is non-login (reads ~/.bashrc). That's
why Ubuntu's ~/.profile sources ~/.bashrc. source file (or .) reloads
it without a new login.
Troubleshooting
5
SymptomCause and fix
command not found, even though the binary exists
Its directory isn't in $PATH. Check echo $PATH; add the directory or call
it by its full path. For something freshly installed, sometimes hash -r
(reset the path cache) or a new shell helps.
export worked, but disappeared in a new terminal
export only lives in the current session. To make it permanent, add it to
~/.bashrc (terminals) or ~/.profile (login), then source it or log back in.
The variable is set in the terminal but not over SSH (or vice versa)
Different files for login/non-login (see the table). SSH reads ~/.profile,
but you set it in ~/.bashrc — move it, or have one source the other.
A script/cron/systemd doesn't see the variable
cron and systemd units do not read your ~/.bashrc. Set it
explicitly: Environment=/EnvironmentFile= in the unit, or inside the
script itself for cron.
sudo "loses" variables
sudo resets the environment (env_reset). Pass it through: sudo -E cmd (if
allowed) or sudo VAR=val cmd (see sudo).
An environment variable holding a colon-separated list of directories where the shell looks up a command given without a /. command -v or which shows which file will run.Also appears in:
nginx, Paths, which / type / whereis, hash and 66 more