What Are Environment Variables?#
Environment variables are key-value pairs that configure the behavior of processes on a Linux system. They’re inherited by child processes, which means setting a variable in your shell makes it available to every command you run from that shell.
echo $HOME
# /home/mikePrograms use environment variables for configuration without hardcoding values — paths, credentials, locale settings, and runtime options are all commonly passed this way.
Viewing Environment Variables#
List all variables#
# All exported environment variables
env
# Or equivalently
printenvPrint a specific variable#
printenv PATH
echo $HOMEShow all variables including shell-local ones#
# Includes unexported shell variables and functions
setSetting Variables#
Temporary (current session only)#
# Set and export in one step
export MY_APP_ENV=production
# Or set first, then export
MY_APP_ENV=production
export MY_APP_ENVFor a single command#
Prefix the command with the variable assignment:
DEBUG=true ./my-script.shThis sets DEBUG only for that command — it doesn’t affect your current shell.
Unsetting a variable#
unset MY_APP_ENVShell Variables vs Environment Variables#
Not every shell variable is an environment variable:
# Shell variable (local to this shell, NOT inherited by child processes)
MY_VAR="hello"
# Environment variable (inherited by child processes)
export MY_VAR="hello"To check if a variable is exported:
# Shows only exported variables
export -p | grep MY_VARPersistent Variables#
Session variables disappear when you close the terminal. To make them persist, add them to shell startup files.
Where to put them#
| File | Scope | When it’s read |
|---|---|---|
~/.bashrc | Current user, interactive shells | Every new interactive bash shell |
~/.bash_profile | Current user, login shells | Login (SSH, TTY, new terminal session) |
~/.profile | Current user, login shells (sh-compatible) | Login, if .bash_profile doesn’t exist |
/etc/environment | All users | Login (PAM), not a script — just KEY=value lines |
/etc/profile | All users | Login shells |
/etc/profile.d/*.sh | All users | Login shells (sourced by /etc/profile) |
Example: add a persistent variable for your user#
echo 'export EDITOR=vim' >> ~/.bashrcReload without logging out:
source ~/.bashrcExample: add a system-wide variable#
# /etc/environment uses simple KEY=value syntax (no export, no shell commands)
sudo sh -c 'echo "JAVA_HOME=/usr/lib/jvm/java-17" >> /etc/environment'Common Environment Variables#
| Variable | Purpose | Typical Value |
|---|---|---|
PATH | Directories to search for commands | /usr/local/bin:/usr/bin:/bin |
HOME | Current user’s home directory | /home/mike |
USER | Current username | mike |
SHELL | Current user’s default shell | /bin/bash |
EDITOR | Default text editor | vim, nano |
LANG | System locale | en_US.UTF-8 |
PWD | Current working directory | /home/mike/projects |
TERM | Terminal type | xterm-256color |
XDG_CONFIG_HOME | User config directory | ~/.config |
LD_LIBRARY_PATH | Additional shared library paths | /usr/local/lib |
The PATH Variable#
PATH is the most important environment variable. It tells the shell where to find executable programs.
echo $PATH
# /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbinThe shell searches directories left to right. The first match wins.
Adding to PATH#
# Prepend (your directory is searched first)
export PATH="$HOME/.local/bin:$PATH"
# Append (searched last)
export PATH="$PATH:/opt/myapp/bin"Make it persistent:
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrcCheck where a command resolves from#
which python3
# /usr/bin/python3
type -a python3
# Shows ALL matches in PATHVariable Expansion#
The shell expands variables before executing commands:
APP_DIR=/opt/myapp
echo "$APP_DIR/bin"
# /opt/myapp/binBraces for disambiguation#
VERSION=3
echo "${VERSION}_final"
# 3_final
# Without braces, shell looks for $VERSION_final (undefined)
echo "$VERSION_final"
# (empty)Default values#
# Use default if variable is unset or empty
echo "${DB_HOST:-localhost}"
# Assign default if unset
: "${DB_PORT:=5432}"
echo $DB_PORT
# 5432Environment Variables in Scripts#
Scripts inherit the environment of the parent shell. You can also load variables from a file:
.env file pattern#
# .env
DB_HOST=localhost
DB_PORT=5432
DB_NAME=myappLoad it into your shell:
export $(grep -v '^#' .env | xargs)Or source it if it uses export:
# .env (with export)
export DB_HOST=localhost
export DB_PORT=5432source .envPassing variables to child processes#
# Only exported variables are inherited
export API_KEY="secret123"
./my-script.sh # can access $API_KEY
# Non-exported variables are NOT inherited
LOCAL_VAR="hello"
./my-script.sh # cannot access $LOCAL_VARInspecting a Process’s Environment#
View the environment of a running process:
# By PID
cat /proc/<pid>/environ | tr '\0' '\n'
# For a specific process
cat /proc/$(pgrep nginx | head -1)/environ | tr '\0' '\n'Best Practices#
- Keep secrets out of shell history — use
read -sor load from files with restricted permissions instead of typingexport SECRET=valuedirectly - Use
/etc/environmentfor system-wide variables that all users and services need - Use
~/.bashrcfor user-specific interactive settings and~/.bash_profilefor login-time setup - Always quote variable expansions (
"$VAR") to prevent word splitting and globbing - Use
${VAR:-default}syntax in scripts to handle missing variables gracefully - Don’t put sensitive values in
/etc/environmentor profile scripts — use secret management tools for production credentials - Prepend to PATH with
$HOME/.local/bin:$PATHrather than overwriting it entirely

