The shell keeps information in environment variables: your user name, your home directory, the list of folders where it looks for commands. Knowing how to read and change them is essential to understand how the system behaves. This guide covers the most common variables and the commands to handle them.
What you will learn
- Show the value of a variable with
echo - List every variable with
env - Create a variable and make it available with
export - Know the essential variables:
PATH,HOME,USER,SHELL - Delete a variable with
unset - Diagnose the "command not found" problem
What is an environment variable?
An environment variable is a name=value pair kept in memory by the shell. Every program started from the terminal inherits these variables.
They configure the behaviour of the system without changing any file.
For example, LANG sets the language of messages and PATH says where to
look for commands.
How do you show a variable?
The echo command followed by $NAME prints the contents of a variable:
echo $HOME/home/bobThe $ sign tells the shell to replace the name with its value. Without
the $, the shell prints the literal text:
echo HOMEHOMEWhich variables are essential?
Here are the variables you will meet most often. They are set by the system at login, and most programs read them:
| Variable | Contents | Example |
|---|---|---|
HOME | Home directory | /home/bob |
USER | Name of the logged-in user | bob |
SHELL | Configured login shell | /bin/bash |
PATH | List of folders where commands are looked up | /usr/local/bin:/usr/bin:/bin |
PWD | Current directory | /home/bob/projects |
LANG | Language and encoding | en_US.UTF-8 |
HOSTNAME | Name of the machine | server01 |
To show any of them, use echo with the $ in front of the name:
echo $USERecho $SHELLecho $LANGHow do you list every variable?
The env command prints every exported environment variable:
envThe output is long. To look for a given variable, combine it with grep:
env | grep PATHPATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/gamesHow do you create a variable?
To create a variable, write NAME=value with no spaces around the =:
FIRSTNAME="Alice"echo $FIRSTNAMEAliceThis writing rule is not a style convention. FIRSTNAME = "Alice"
causes an error, because the shell then reads FIRSTNAME as a
command to run, with = and "Alice" as arguments. The message therefore
speaks of a command not found and never mentions the assignment.
Always write NAME=value, with no space on either side.
Local vs exported variable
A variable created with NAME=value only exists in the current shell. The
programs started from that shell do not see it.
To make it visible to child programs, use export:
export FIRSTNAME="Alice"To check, start a subshell and print the variable:
bash -c 'echo $FIRSTNAME'Without export, the result is empty. With export, the value shows.
Create and export in one go
You can create and export in a single line:
export PROJECT="my-site"How does PATH work?
PATH is the most important variable for running commands. It holds a
list of folders separated by a colon, the : character. Remember this
separator, it is neither the space nor the comma: a value written with the
wrong character produces no error, it simply makes every folder in the list
invisible.
echo $PATH/usr/local/bin:/usr/bin:/binWhen you type a command such as ls, the shell looks for a file named
ls in each folder of PATH, in order:
- It looks in
/usr/local/bin/→ not found - It looks in
/usr/bin/→ found! It runs/usr/bin/ls
You can check where a command lives with which, which follows the same order as the shell:
which ls/usr/bin/lsAdd a folder to PATH
To add a folder temporarily (for example ~/scripts), put it in front of the existing $PATH:
export PATH="$HOME/scripts:$PATH"This change is temporary: it disappears when the terminal closes. To make it
permanent, add the line to ~/.bashrc (see the
Customise your shell guide).
How do you delete a variable?
The unset command deletes a variable, which you can check with a second echo:
export TEST="hello"echo $TESTunset TESTecho $TESTThe last line prints nothing: the variable no longer exists.
Troubleshooting
Variable problems all look the same: nothing shows up, or a command stays
not found, and no message mentions a variable. Two causes cover most
cases, a folder missing from PATH and a setting written in the wrong
configuration file. The table sorts them by symptom, since that is what you
observe.
| Symptom | Likely cause | Fix |
|---|---|---|
command: command not found | The folder holding the command is not in $PATH | echo $PATH then export PATH="/missing/path:$PATH" |
echo $MY_VAR shows nothing | Variable not defined or not exported | Check with env | grep MY_VAR |
| Variable lost after closing the terminal | Variable not added to .bashrc | Add export MY_VAR="value" to ~/.bashrc |
NAME = value gives an error | Spaces around the = | Write NAME=value with no spaces |
| A child program does not see the variable | export forgotten | Use export NAME=value |
Variable missing with ssh host 'command' although it works in an interactive session | It is declared in ~/.bash_profile, never read in that case | Declare it in ~/.bashrc, at the top of the file on Debian/Ubuntu: that is the file a remote command reads |
~/.bashrc ignored although it exists | Bash stops at the first of the three login files found | Check for ~/.bash_profile then ~/.bash_login: the first one found hides the next ones |
Why does a variable disappear in automation?
This point explains almost every "my variable works over interactive SSH and
disappears in the script", and it contradicts the usual shortcut,
".bash_profile for login shells, .bashrc for interactive shells".
A remote command is neither one nor the other. Measured on AlmaLinux 10 with probes in both files:
ssh server 'echo "$-"; shopt -q login_shell && echo login || echo non-login'hBcnon-login$- contains no i, so the session is not interactive,
and it is not a login shell either. Yet only the probe in
~/.bashrc fired: bash reads it in this precise case, on the strength of
the SSH_CLIENT variable.
One caveat applies to Debian and Ubuntu: their default ~/.bashrc
opens with a guard that returns as soon as $- contains no i. Bash does
read the file, but only runs these few lines of it:
# If not running interactively, don't do anythingcase $- in *i*) ;; *) return;;esacOn these distributions, a variable meant for remote commands is therefore declared above this block, at the top of the file. Placed further down, it is never read, again without the slightest error message.
A corollary follows for the reading order. At login, bash
stops at the first file found among ~/.bash_profile,
~/.bash_login and ~/.profile, and never reads the others.
Settings placed in ~/.profile while a ~/.bash_profile exists are
therefore never applied, without the slightest message.
Put it into practice
Reading a guide about variables does not replace the moment when your own export survives (or not) in a subshell. This lab has you write an env.sh file that exports variables, reuses one inside another and adds a directory at the front of PATH: the whole thing is checked by loading it with source in a fresh shell.
Key points
- An environment variable is a name=value pair inherited by child programs.
echo $NAMEshows the value,envlists every exported variable.exportmakes a variable visible to subprocesses.PATHdecides where the shell looks for commands.- Changes are temporary unless added to
~/.bashrc. unsetdeletes a variable.
Knowledge check
Check that the essentials of this guide stuck. The questions cover only what has just been explained here.
Knowledge check
Check what you have learned with this interactive quiz
How it works
- The timer starts when you click Start
- Multiple choice, true/false and short answer questions
- You can move between questions
- Detailed results are shown at the end
Starts the quiz and the timer
Review
(0/0)Score by domain
A domain groups several guides and gets several questions, so its score is more reliable than a per-topic score, which often rests on a single question.
Summary
Strengths
No topic passed at 80% on at least two questions yet.
Weak areas
No topic below the pass mark.
Recommended next
Hints before you try again?
Continue the course: Shell expansions
A new full quiz with random questions
Work again only on the questions you missed