Environment variables are named values that programs inherit from the process that started them: PATH tells the shell where to find commands, HOME points to your home directory, and applications read settings like DATABASE_URL or NODE_ENV from them. Knowing where they come from — and where they don’t reach — solves a lot of “works in my shell, fails in cron” puzzles.
View variables
printenv # all environment variables
printenv PATH # one variable
echo "$HOME"
env | grep -i proxy
set (without arguments) shows shell variables and functions too — more than the environment.
Set a variable
GREETING="hello" # shell variable: only this shell sees it
export GREETING # now child processes inherit it
export APP_ENV=production # set and export in one step
A plain assignment creates a shell variable. export turns it into an environment variable, passed to programs you start from this shell.
For a single command only:
APP_ENV=staging ./run.sh
Remove it:
unset GREETING
Make it permanent for your user
Add export lines to a startup file:
~/.bashrc— read by interactive non-login shells (most terminal windows, and on Debian/Ubuntu also sourced by login shells via~/.profile).~/.profileor~/.bash_profile— read by login shells (SSH logins).
echo 'export EDITOR=nano' >> ~/.bashrc
source ~/.bashrc
The differences between these files are covered in .bashrc vs .bash_profile.
System-wide
/etc/environment— simpleKEY=valuelines (noexport, no variable expansion), read at login by PAM for all users:
HTTP_PROXY=http://10.0.0.1:3128
/etc/profile.d/*.sh— shell scripts sourced by login shells, so you can use logic andexport:
# /etc/profile.d/java.sh
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
export PATH="$JAVA_HOME/bin:$PATH"
Changes apply at the next login.
PATH
PATH is a colon-separated list of directories searched for commands, in order:
echo "$PATH"
export PATH="$HOME/.local/bin:$PATH" # prepend a directory
Always include $PATH when changing it, or you’ll lose access to normal commands for that session. See the PATH variable.
Where variables don’t reach
Environment variables flow from parent to child process. That’s why these common surprises happen:
systemd services
Services don’t read your .bashrc or /etc/profile. Set variables in the unit:
[Service]
Environment=NODE_ENV=production PORT=3000
EnvironmentFile=/etc/myapp/env
EnvironmentFile reads KEY=value lines — a good place for secrets (chmod 600). Apply with systemctl daemon-reload and a restart. See systemd unit files.
cron
Cron runs jobs with a minimal environment (typically PATH=/usr/bin:/bin). Define what you need at the top of the crontab, or source a file in the job:
PATH=/usr/local/bin:/usr/bin:/bin
0 3 * * * . /etc/myapp/env; /usr/local/bin/backup.sh
See cron environment variables.
sudo
sudo resets the environment for security (env_reset), keeping only a safe list. To pass something through:
sudo --preserve-env=HTTP_PROXY apt update
sudo -E command # preserve everything (if sudoers allows it)
sudo VAR=value command # set for that command
Docker containers
Containers get only the variables you pass: -e, --env-file or Compose’s environment:. See Docker environment variables.
.env files for applications
Many frameworks load a .env file from the project directory (Laravel, Node with dotenv, Django with django-environ). That’s application-level, not the shell environment. Load one into your shell for testing:
set -a; source .env; set +a
set -a exports every variable assigned while it’s active.
Secrets in environment variables
Convenient, but visible to the process owner and root (/proc/<pid>/environ), and sometimes leaked through crash reports or debug pages. Keep secret files chmod 600, never commit .env to Git, and turn off debug modes in production.
Useful variables
| Variable | Meaning |
|---|---|
PATH |
Command search path |
HOME |
Home directory |
USER / LOGNAME |
Current user |
SHELL |
Login shell |
EDITOR / VISUAL |
Default editor |
LANG / LC_ALL |
Locale |
TZ |
Time zone override |
HTTP_PROXY / HTTPS_PROXY / NO_PROXY |
Proxy settings |
TERM |
Terminal type |
Quick reference
| Task | Command |
|---|---|
| Show one | printenv NAME |
| Set for session | export NAME=value |
| Set for one command | NAME=value cmd |
| Remove | unset NAME |
| Persist (user) | add to ~/.bashrc |
| Persist (system) | /etc/environment or /etc/profile.d/ |
| For a service | Environment= / EnvironmentFile= |
Related: bash scripting tutorial.