LFCA 60 ๐ง Environment Variables Explained
Every process on a Linux system carries a small set of hidden values โ strings like HOME=/home/alice, PATH=/usr/bin:/bin, LANG=en_US.UTF-8 โ that shape how programs behave. These are environment variables. They are the reason ls finds your commands without a full path, the reason date prints in your language, and the reason sudo knows which home directory to use when you switch users. Understanding them is not optional for anyone managing a Linux system, and the LFCA exam expects you to know how to view, set, persist, and debug them.
This chapter covers what environment variables are, how they differ from shell variables, the commands used to inspect and modify them, the files that make them persistent, and the specific variables โ PATH, HOME, USER, PWD, SHELL, LANG, LC_ALL, TERM, EDITOR, LD_LIBRARY_PATH, DISPLAY โ that you will encounter in every system.
Key point: An environment variable is a name-value pair inherited by a process from its parent. A shell variable exists only inside the current shell. The export command converts a shell variable into an environment variable, making it visible to any child process the shell launches. The rule is precise: environment variables are “global” โ inherited by children; shell variables are “local” โ invisible to children .
Why environment variables exist
A Linux system runs hundreds of processes simultaneously. Each process needs configuration: where to find its libraries, which user it is running as, which language to use for messages, where temporary files should go. Hardcoding these values into every program would make the system brittle. Environment variables provide a dynamic, per-process configuration layer.
The command search problem. When you type ls, the shell does not search the entire filesystem. It searches the directories listed in PATH, one by one, from left to right, and runs the first matching executable it finds . This is why PATH is the most important environment variable in daily use โ it determines which version of a command runs when multiple versions are installed.
The user context problem. A login shell needs to know who you are (USER), where your home directory is (HOME), and what shell you are using (SHELL). These are set automatically at login, but they can be overridden or modified .
The localization problem. The LANG and LC_ALL variables control the language of error messages, date formats, and character encoding. A script that parses dates or compares strings may behave differently under different locales .
The configuration problem. Many applications read environment variables instead of configuration files. The EDITOR variable tells crontab, git, and visudo which editor to open. The LD_LIBRARY_PATH variable tells the dynamic linker where to find shared libraries .
The trade-off. Environment variables are convenient but invisible. There is no central registry of “all variables a program might read.” Debugging environment issues often means using strace or reading source code. Documentation is the only reliable guide.
a. Environment Variables vs Shell Variables
The distinction between environment and shell variables is the foundation of everything else.
A shell variable is created with name=value and exists only in the current shell session. It is invisible to any command or script the shell launches. A environment variable is a shell variable that has been marked for export. When the shell launches a child process, it copies all exported variables into that process’s environment .
#!/bin/bash
MY_VAR="hello" # shell variable only
echo "$MY_VAR" # hello โ works in current shell
bash -c 'echo "$MY_VAR"' # empty โ child process does not inherit it
export MY_VAR # now it is an environment variable
bash -c 'echo "$MY_VAR"' # hello โ child inherits it
The export command marks a variable for export. It can be combined with assignment: export MY_VAR="hello". The -n option (export -n VAR) reverses the export, turning an environment variable back into a shell variable .
By convention, environment variables are named in UPPERCASE, and shell variables are lowercase. This is not enforced by the shell, but it is followed universally and makes code more readable .
The env and printenv commands display the current environment โ the set of exported variables. The set command displays all shell variables, including non-exported ones .
env # all environment variables
printenv # same, can also query one: printenv PATH
set # all shell variables (and functions)
echo $PATH # value of one variable
When a program is invoked, Bash constructs its environment from the shell’s current environment: the initial inherited environment, plus any variables added with export, minus any removed with unset . This is the complete picture of how variables propagate.
b. The Common Variables You Will See
Linux systems set a standard set of environment variables at login. These appear in every interactive session and in every script.
PATH is a colon-separated list of directories. The shell searches them in order when you type a command without a slash . A typical value is /usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games . A zero-length directory name โ indicated by two adjacent colons or a leading/trailing colon โ is treated as the current directory. This is a security risk and is rarely intentional .
HOME is the absolute path to the user’s home directory. It is used by cd when called without arguments, by ~ expansion in the shell, and by countless applications to find dotfiles .
USER is the username of the current user. It is set at login and not usually changed. LOGNAME is a related variable set by the login process.
PWD is the absolute path of the current working directory. It is updated automatically by cd. OLDPWD is the previous directory, used by cd - .
SHELL is the absolute path to the user’s login shell. It is not necessarily the shell currently running โ if you launch bash from zsh, SHELL still points to zsh .
TERM identifies the terminal type, such as xterm-256color or screen. Programs use it to determine what escape sequences are supported.
LANG and LC_ALL control localization. LANG sets the default locale; LC_ALL overrides all other locale settings. Common values are en_US.UTF-8, C, or POSIX. The C locale is the portable default with no localization .
EDITOR and VISUAL specify the default text editor for programs that need one. If both are set, VISUAL usually takes precedence .
LD_LIBRARY_PATH is a colon-separated list of directories the dynamic linker searches for shared libraries before the standard system paths. It is commonly used to run applications with custom libraries installed in non-standard locations .
DISPLAY identifies the X Window System display server. It is used by GUI applications and remote X sessions .
c. Making Variables Persistent
A variable set on the command line disappears when the shell exits. To make it permanent, it must be defined in a shell configuration file that is sourced at the start of every session .
The correct file depends on the type of shell and the type of session.
For login shells (SSH sessions, TTY logins, su -), Bash reads ~/.bash_profile, ~/.bash_login, or ~/.profile โ the first one that exists .
For interactive non-login shells (new terminal windows in a GUI session), Bash reads ~/.bashrc .
For system-wide configuration applying to all users, the files are /etc/profile and /etc/bash.bashrc . For values that should be set once at login for every user regardless of shell, /etc/environment is the standard location. This file uses a simple KEY=value format and does not support export or shell syntax โ it is parsed by the PAM pam_env module .
# Add to ~/.bashrc for a user-specific persistent variable
export MY_VAR="hello"
# Add to /etc/environment for a system-wide variable (no export keyword)
MY_VAR=hello
After editing a configuration file, source it to apply changes to the current session: source ~/.bashrc. A new login or terminal session will pick up the change automatically .
Complete Example Session
This session demonstrates viewing, creating, exporting, persisting, and removing environment variables.
#!/bin/bash
# env-demo.sh - Demonstrates environment variable operations
# ============================================
# PART 1: VIEWING THE ENVIRONMENT
# ============================================
env # all environment variables
printenv PATH # one variable
printenv | grep USER # filter the list
echo "$HOME" # reference a variable
set | grep MY_ # all shell variables matching
# ============================================
# PART 2: SHELL VARIABLE VS ENVIRONMENT VARIABLE
# ============================================
MY_VAR="hello" # shell variable
echo "$MY_VAR" # hello
bash -c 'echo "$MY_VAR"' # empty โ not exported
export MY_VAR # mark for export
bash -c 'echo "$MY_VAR"' # hello โ now inherited
# ============================================
# PART 3: SETTING IN ONE LINE
# ============================================
export GREETING="Hello World"
echo "$GREETING"
# ============================================
# PART 4: UNSETTING
# ============================================
unset GREETING
echo "$GREETING" # empty
# ============================================
# PART 5: THE PATH VARIABLE
# ============================================
echo "$PATH" # colon-separated directories
# Prepend a directory (takes precedence)
export PATH="/opt/myapp/bin:$PATH"
# Append a directory (fallback)
export PATH="$PATH:/opt/other/bin"
# ============================================
# PART 6: READING A VARIABLE WITH A DEFAULT
# ============================================
echo "${UNSET_VAR:-default}" # prints "default" if unset
echo "${UNSET_VAR:=default}" # assigns "default" if unset
# ============================================
# PART 7: PERSISTENT VARIABLE IN ~/.bashrc
# ============================================
# Add this line to ~/.bashrc:
# export MY_PERSISTENT_VAR="persistent value"
# Then reload:
# source ~/.bashrc
# ============================================
# PART 8: SYSTEM-WIDE VARIABLE IN /etc/environment
# ============================================
# Add this line to /etc/environment (no export):
# GLOBAL_VAR="available to all users"
# Log out and back in to apply.
# ============================================
# PART 9: USING VARIABLES IN A SCRIPT
# ============================================
#!/bin/bash
# greeting.sh
echo "${GLOBAL_GREETING}! Welcome to the system."
# ============================================
# PART 10: DEBUGGING WITH env
# ============================================
# Run a command with a modified environment
env MY_VAR="temp" bash -c 'echo "$MY_VAR"'
# See what environment a process has
# cat /proc/$$/environ | tr '\0' '\n'
The ten parts cover viewing, the shell vs environment distinction, one-line export, unset, PATH manipulation, default values, persistence in ~/.bashrc, global variables in /etc/environment, script usage, and debugging.
Quick Reference
The Commands
| Command | Purpose |
|---|---|
env | Display all environment variables |
printenv | Display all, or one by name |
set | Display all shell variables |
export VAR | Mark variable for export |
export VAR=value | Set and export in one step |
unset VAR | Remove a variable |
export -n VAR | Un-export, keep as shell variable |
The Common Variables
| Variable | Meaning |
|---|---|
PATH | Directories searched for commands |
HOME | User’s home directory |
USER | Current username |
PWD | Current working directory |
SHELL | Login shell path |
TERM | Terminal type |
LANG / LC_ALL | Locale settings |
EDITOR / VISUAL | Default editor |
LD_LIBRARY_PATH | Shared library search path |
DISPLAY | X display server |
The Persistence Files
| File | Scope | Shell Type |
|---|---|---|
~/.bashrc | User | Interactive non-login |
~/.bash_profile | User | Login |
~/.profile | User | Login (fallback) |
/etc/profile | All users | Login |
/etc/bash.bashrc | All users | Non-login |
/etc/environment | All users | Login (PAM) |
Best Practices
โ Do This:
export MY_VAR="value" # โ
export when child processes need it
if [ -z "$MY_VAR" ]; then # โ
check before use
echo "MY_VAR is not set"
fi
export PATH="/opt/app/bin:$PATH" # โ
prepend to override system commands
# Add to ~/.bashrc for user persistence
export EDITOR="vim" # โ
# Add to /etc/environment for global
GLOBAL_VAR="value" # โ
no export keyword
โ Don’t Do This:
MY_VAR="hello" # โ not visible to child processes
./script.sh
export PATH="$PATH:." # โ current directory in PATH is a security risk
export GREETING="Hello" # โ lost when shell exits
# (not added to .bashrc)
# In /etc/environment:
export GLOBAL_VAR="value" # โ export not supported
echo $UNSET_VAR # โ empty output, no warning
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Variable not visible in script | Not exported | Use export VAR |
PATH override breaks commands | Replaced instead of appended | Use PATH="$PATH:/new" |
| Variable lost after logout | Set in shell, not config file | Add export to ~/.bashrc |
| Global variable not available | Added to shell config, not /etc/environment | Edit /etc/environment |
export error in /etc/environment | File parsed by PAM, not shell | Remove export keyword |
| Script uses wrong command version | PATH order | Check which -a cmd |
Real-World Examples
1. View All Environment Variables
env
2. Check a Specific Variable
printenv PATH
3. Set a Temporary Variable
export API_KEY="abc123"
4. Remove a Variable
unset API_KEY
5. Prepend to PATH
export PATH="/opt/custom/bin:$PATH"
6. Default Value Fallback
DB_HOST="${DB_HOST:-localhost}"
7. Persist in .bashrc
# ~/.bashrc
export EDITOR="vim"
8. Global in /etc/environment
# /etc/environment
JAVA_HOME="/usr/lib/jvm/default"
9. Use in a Script
#!/bin/bash
echo "User: $USER"
echo "Home: $HOME"
10. Temporary Override for One Command
env LANG=C date
Visual: Shell vs Environment Variables
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SHELL VARIABLE vs ENVIRONMENT VARIABLE โ
โ โ
โ Shell variable: โ
โ MY_VAR="hello" โ
โ โโ exists only in current shell โ
โ โโ child processes do NOT inherit it โ
โ โ
โ Environment variable: โ
โ export MY_VAR="hello" โ
โ โโ exists in current shell AND children โ
โ โโ child processes inherit it โ
โ โ
โ Parent shell โ
โ โโ MY_VAR=hello (exported) โ
โ โโ launches child process โ
โ โโ receives MY_VAR=hello โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: How PATH Works
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ PATH SEARCH โ
โ โ
โ You type: ls โ
โ โ โ
โ โผ โ
โ Shell checks PATH: โ
โ /usr/local/bin:/usr/bin:/bin โ
โ โ โ
โ โผ โ
โ /usr/local/bin/ls? โ not found โ
โ โ โ
โ โผ โ
โ /usr/bin/ls? โ FOUND โ execute โ
โ โ
โ First match wins. โ
โ Order matters. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Persistence File Hierarchy
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ WHERE TO PUT PERSISTENT VARIABLES โ
โ โ
โ User-specific: โ
โ ~/.bashrc โ every interactive shell โ
โ ~/.bash_profile โ every login shell โ
โ โ
โ System-wide: โ
โ /etc/profile โ every user, login โ
โ /etc/bash.bashrc โ every user, interactive โ
โ /etc/environment โ every user, login โ
โ (no export keyword) โ
โ โ
โ Edit โ source โ new session verifies โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: export and unset Flow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ export / unset FLOW โ
โ โ
โ MY_VAR="hello" โ shell variable โ
โ โ โ
โ โผ โ
โ export MY_VAR โ now environment โ
โ โ โ
โ โผ โ
โ child process โ inherits MY_VAR โ
โ โ โ
โ โผ โ
โ unset MY_VAR โ removed everywhere โ
โ โ โ
โ โผ โ
โ echo $MY_VAR โ empty โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Item | Value |
|---|---|
| Definition | Name-value pair inherited by processes |
| Shell variable | Local to current shell |
| Environment variable | Exported, inherited by children |
| Export | export VAR or export VAR=value |
| Remove | unset VAR |
| View all | env or printenv |
| View shell vars | set |
| PATH | Colon-separated command search dirs |
| User persistence | ~/.bashrc |
| Global persistence | /etc/environment (no export) |
Key takeaways:
- Environment variables are inherited by child processes; shell variables are not. The
exportcommand is the switch that makes a variable part of the environment . PATHis a colon-separated list of directories. The shell searches them left to right for executable files. Putting the current directory (.) inPATHis a security risk .env,printenv, andsetdisplay different things.envandprintenvshow exported variables.setshows all shell variables, including functions .- Persistence requires editing a configuration file.
~/.bashrcfor user-specific interactive shells./etc/environmentfor system-wide, login-time variables./etc/environmentdoes not supportexport. - The common variables have specific roles.
HOME,USER,PWD,SHELL,TERM,LANG,EDITORโ each controls a different aspect of the session . unsetremoves a variable from the current session. If it is defined in a configuration file, it will return in new sessions unless you also edit the file .- Use
${VAR:-default}to provide a fallback. This works without modifying the variable itself.
Remember: Environment variables are the invisible configuration layer of a Linux system. They tell programs where to find things, who is running, what language to speak, and where to store data. export makes a variable visible to children. Configuration files make it persistent. env and printenv show you what is set. The PATH variable is the one you will use every day โ it determines which commands run. Master the distinction between shell and environment variables, and the rest follows.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!