Skip to main content

Understanding Linux Environment Variables

·784 words·4 mins
Linux Learning Lab
Author
Linux Learning Lab
Writing about code, tools, and workflows.

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/mike

Programs 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
printenv

Print a specific variable#

printenv PATH
echo $HOME

Show all variables including shell-local ones
#

# Includes unexported shell variables and functions
set

Setting 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_ENV

For a single command
#

Prefix the command with the variable assignment:

DEBUG=true ./my-script.sh

This sets DEBUG only for that command — it doesn’t affect your current shell.

Unsetting a variable
#

unset MY_APP_ENV

Shell 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_VAR

Persistent Variables
#

Session variables disappear when you close the terminal. To make them persist, add them to shell startup files.

Where to put them
#

FileScopeWhen it’s read
~/.bashrcCurrent user, interactive shellsEvery new interactive bash shell
~/.bash_profileCurrent user, login shellsLogin (SSH, TTY, new terminal session)
~/.profileCurrent user, login shells (sh-compatible)Login, if .bash_profile doesn’t exist
/etc/environmentAll usersLogin (PAM), not a script — just KEY=value lines
/etc/profileAll usersLogin shells
/etc/profile.d/*.shAll usersLogin shells (sourced by /etc/profile)

Example: add a persistent variable for your user
#

echo 'export EDITOR=vim' >> ~/.bashrc

Reload without logging out:

source ~/.bashrc

Example: 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
#

VariablePurposeTypical Value
PATHDirectories to search for commands/usr/local/bin:/usr/bin:/bin
HOMECurrent user’s home directory/home/mike
USERCurrent usernamemike
SHELLCurrent user’s default shell/bin/bash
EDITORDefault text editorvim, nano
LANGSystem localeen_US.UTF-8
PWDCurrent working directory/home/mike/projects
TERMTerminal typexterm-256color
XDG_CONFIG_HOMEUser config directory~/.config
LD_LIBRARY_PATHAdditional 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:/sbin

The 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"' >> ~/.bashrc

Check where a command resolves from
#

which python3
# /usr/bin/python3

type -a python3
# Shows ALL matches in PATH

Variable Expansion
#

The shell expands variables before executing commands:

APP_DIR=/opt/myapp
echo "$APP_DIR/bin"
# /opt/myapp/bin

Braces 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
# 5432

Environment 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=myapp

Load 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=5432
source .env

Passing 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_VAR

Inspecting 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 -s or load from files with restricted permissions instead of typing export SECRET=value directly
  • Use /etc/environment for system-wide variables that all users and services need
  • Use ~/.bashrc for user-specific interactive settings and ~/.bash_profile for 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/environment or profile scripts — use secret management tools for production credentials
  • Prepend to PATH with $HOME/.local/bin:$PATH rather than overwriting it entirely