Table of Contents
- What Are Environment Variables?
- Definition and Purpose
- Types of Environment Variables (Global vs. Local)
- How Environment Variables Work in Linux
- Storage and Inheritance
- Shell Sessions and Lifespan
- Viewing Environment Variables
- Commands:
env,printenv, andecho - Filtering and Searching Variables
- Commands:
- Creating and Modifying Environment Variables
- Local Variables vs. Environment Variables
- The
exportCommand - Unsetting Variables with
unset
- Making Variables Persistent
- User-Specific Configuration Files (
.bashrc,.bash_profile) - System-Wide Configuration Files (
/etc/environment,/etc/profile) - When to Use Which File?
- User-Specific Configuration Files (
- Common Environment Variables You Should Know
PATH: The Executable Search PathHOME,USER, andSHELL: User ContextLANGandLC_*: Locale and Language SettingsPWDandOLDPWD: Current and Previous DirectoriesTERMandEDITOR: Terminal and Editor Preferences
- Advanced Usage of Environment Variables
- Passing Variables to Child Processes
- Modifying
PATHTemporarily vs. Permanently - Using Variables in Shell Scripts
- Environment Variables in Systemd Services and Docker
- Troubleshooting Common Environment Variable Issues
- “Command Not Found” (PATH Issues)
- Variables Not Persisting Across Sessions
- Permission Errors with System-Wide Files
- Best Practices for Managing Environment Variables
- Naming Conventions
- Avoiding Overwrites of System Variables
- Documenting Custom Variables
- Security: Handling Sensitive Data
- Conclusion
- References
1. What Are Environment Variables?
Definition and Purpose
Environment variables are dynamic key-value pairs that store configuration data used by the operating system and applications. They act as a “bridge” between the system, the user, and running processes, providing context that influences behavior. For example:
- The
PATHvariable tells the shell which directories to search for executable programs. - The
HOMEvariable defines the default directory for a user (e.g.,/home/john). - The
LANGvariable sets the system’s default language and character encoding.
Types of Environment Variables
Environment variables in Linux are broadly categorized into two types:
Global (Environment) Variables
These are available to all processes running in the current shell session and any child processes spawned from it. They are inherited by subshells and applications. Examples include PATH, HOME, and USER.
Local Variables
These are only visible to the current shell session and are not inherited by child processes. They are temporary and useful for scripting or short-term tasks. For example, you might set a local variable like temp_dir="/tmp/myfiles" to use in a single terminal session.
2. How Environment Variables Work in Linux
Storage and Inheritance
Environment variables are stored in the memory of the current shell session. When a new process (e.g., a script or application) is launched, it inherits a copy of the parent shell’s environment variables. This “copy-on-write” behavior means changes to a variable in the child process do not affect the parent, and vice versa.
Shell Sessions and Lifespan
- Temporary Lifespan: Variables created in a terminal session (without persistence) exist only until the session is closed.
- Persistent Lifespan: Variables defined in configuration files (like
.bashrc) are loaded every time a new shell session starts, making them persistent across reboots.
3. Viewing Environment Variables
To work with environment variables, you first need to know how to list them. Here are the most common commands:
env: List All Environment Variables
The env command prints all global environment variables in the current shell session:
env
Sample output (truncated):
USER=john
HOME=/home/john
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
LANG=en_US.UTF-8
...
printenv: Print Specific Variables
printenv works similarly to env but lets you filter for a specific variable by name:
printenv PATH # Print the PATH variable
printenv HOME # Print the HOME variable
echo $VAR_NAME: Quick Check
The simplest way to view a single variable is with echo and the $ symbol (which denotes a variable):
echo $USER # Output: john
echo $PWD # Output: /home/john/documents
Filtering with grep
To search for variables matching a keyword (e.g., “PATH”), pipe env or printenv to grep:
env | grep PATH # Find all variables containing "PATH"
4. Creating and Modifying Environment Variables
Local Variables vs. Environment Variables
Before creating variables, it’s critical to distinguish between local and environment variables:
-
Local Variables: Defined with
VAR=value; visible only to the current shell.
Example:my_var="Hello, Linux!" # Local variable echo $my_var # Output: Hello, Linux!If you launch a child process (e.g.,
bashto start a subshell),my_varwill not be available there. -
Environment Variables: Defined with
export VAR=value; visible to the current shell and all child processes.
Example:export my_env_var="I'm global!" # Environment variable echo $my_env_var # Output: I'm global!Now, if you run
bashto start a subshell and checkmy_env_var, it will exist there too.
Modifying Variables
To update an existing variable, redefine it:
export PATH="$PATH:/new/directory" # Add /new/directory to PATH
echo $PATH # Verify the change
Unsetting Variables
Use the unset command to delete a variable:
unset my_env_var # Remove the variable
echo $my_env_var # Output: (empty)
5. Making Variables Persistent
Variables created in a terminal session are temporary—they vanish when the session closes. To make them persistent, you need to define them in shell configuration files.
User-Specific Configuration Files
These files apply only to your user account and are loaded when you start a new shell session:
.bashrc (Most Common)
Loaded by interactive non-login shells (e.g., opening a terminal). Use this for variables you want in everyday terminal sessions.
To edit:
nano ~/.bashrc # Or use your preferred editor (vim, code, etc.)
Add your variable at the end:
export MY_APP_CONFIG="/home/john/.myapp/config"
Save and reload the file to apply changes immediately:
source ~/.bashrc # Or: . ~/.bashrc
.bash_profile (or .profile)
Loaded by login shells (e.g., logging in via SSH or the system console). Use this for variables needed at login (e.g., setting PATH for GUI apps).
On some systems, .bash_profile may source .bashrc by default, so variables in .bashrc may already be available here.
System-Wide Configuration Files
These files apply to all users and require root privileges to modify:
/etc/environment
A simple file for setting environment variables system-wide. It uses KEY=VALUE syntax (no export needed):
sudo nano /etc/environment
Add:
GLOBAL_VAR="This applies to all users"
Changes take effect after a reboot or when a new login shell starts.
/etc/profile and /etc/bash.bashrc
/etc/profile is loaded by login shells for all users, and /etc/bash.bashrc by interactive shells system-wide. These files often source scripts in /etc/profile.d/ (a directory for modular configuration).
Warning: Modifying system-wide files can affect all users and system stability. Use them only for variables critical to all accounts (e.g., adding a system-wide PATH directory).
When to Use Which File?
| Scenario | File to Use |
|---|---|
| Variables for your terminal sessions | ~/.bashrc |
| Variables for login (e.g., SSH, console) | ~/.bash_profile |
| System-wide variables (all users) | /etc/environment |
| System-wide bash-specific settings | /etc/bash.bashrc |
6. Common Environment Variables You Should Know
Linux defines dozens of built-in environment variables. Here are the most essential ones:
PATH: The Executable Search Path
Purpose: Tells the shell which directories to search for executable programs.
Example:
echo $PATH
# Output: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
When you run ls, the shell searches each directory in PATH (in order) until it finds /bin/ls.
Tip: To add a custom directory (e.g., ~/bin) to PATH permanently, add this to ~/.bashrc:
export PATH="$HOME/bin:$PATH" # Prepend ~/bin to PATH (runs before system directories)
HOME, USER, and SHELL
HOME: Your user’s home directory (e.g.,/home/john).USER: Your username (e.g.,john).SHELL: The path to your default shell (e.g.,/bin/bashor/usr/bin/zsh).
LANG and LC_*: Locale Settings
LANG: Default language and character encoding (e.g.,en_US.UTF-8for US English with UTF-8).LC_TIME: Date/time format (e.g.,en_GB.UTF-8for UK-style dates).LC_MONEY: Currency format, etc.
PWD and OLDPWD
PWD: Current working directory (e.g.,/home/john/docs).OLDPWD: Previous working directory (updated when you runcd).
TERM and EDITOR
TERM: Terminal type (e.g.,xterm-256color), used by applications to format output.EDITOR: Default text editor (e.g.,nano,vim). Many tools (likegit) use this to open files.
7. Advanced Usage of Environment Variables
Passing Variables to Child Processes
As mentioned earlier, environment variables are inherited by child processes. This is critical for scripting:
# Script: my_script.sh
echo "Received variable: $MY_VAR"
Run it with a custom variable:
MY_VAR="Hello from parent" bash my_script.sh # Output: Received variable: Hello from parent
Modifying PATH Temporarily vs. Permanently
- Temporary: Add a directory to
PATHfor the current session only:PATH="$PATH:/tmp/mytools" # No export needed (PATH is already an environment variable) - Permanent: Add to
~/.bashrcor/etc/environment(as shown earlier).
Environment Variables in Systemd Services
Systemd services can define environment variables in their .service files using Environment= or EnvironmentFile=:
# /etc/systemd/system/myapp.service
[Service]
Environment="APP_PORT=8080"
EnvironmentFile=/etc/myapp/env # Load variables from a file
ExecStart=/usr/bin/myapp
Environment Variables in Docker
Docker containers can receive environment variables via the -e flag or --env-file:
docker run -e "DB_HOST=localhost" -e "DB_USER=admin" myapp # Pass variables directly
docker run --env-file .env myapp # Load from a .env file
8. Troubleshooting Common Environment Variable Issues
”Command Not Found” (PATH Issues)
If you get “command not found” when running a program, its directory is likely missing from PATH.
Fix:
export PATH="$PATH:/path/to/program/directory" # Temporarily add it
# Or permanently add to ~/.bashrc
Variables Not Persisting Across Sessions
If a variable disappears after closing the terminal, you forgot to add it to a configuration file (e.g., .bashrc).
Fix:
nano ~/.bashrc # Add the variable here with export
source ~/.bashrc # Reload
Permission Errors with System-Wide Files
If you can’t edit /etc/environment or /etc/profile, you need root privileges.
Fix: Use sudo (e.g., sudo nano /etc/environment).
9. Best Practices for Managing Environment Variables
Naming Conventions
- Use uppercase for environment variables (e.g.,
MY_APP_CONFIG). - Use lowercase for local variables (e.g.,
temp_file). - Avoid spaces or special characters (use underscores
_instead).
Avoid Overwriting System Variables
Never overwrite critical system variables like PATH, HOME, or USER unless you’re certain of the consequences. For example, export PATH="/new/dir" (without $PATH) will erase all default directories!
Document Custom Variables
If you define custom variables, add comments in your .bashrc or a separate ~/.env file to explain their purpose:
# ~/.bashrc
# Custom path for my Python scripts
export PY_SCRIPTS="$HOME/scripts/python"
Security: Handling Sensitive Data
Never store secrets (passwords, API keys) in plaintext in configuration files. Instead:
- Use tools like
passorsecretsmanagerfor encryption. - Load secrets from secure files with restricted permissions (e.g.,
chmod 600 ~/.secrets).
10. Conclusion
Environment variables are the backbone of Linux flexibility, enabling your system and applications to adapt to users, workflows, and environments. From defining where to find programs (PATH) to configuring user-specific settings (HOME), they simplify daily tasks and power complex systems.
By mastering environment variables—how to view, create, persist, and troubleshoot them—you gain deeper control over your Linux system. Whether you’re a developer, sysadmin, or casual user, this knowledge will streamline your workflow and help you debug issues faster.