Linux··4 min

Environment Variables and the Shell

Every time you open a terminal the shell sets up an environment — variables that control how it and every program you run behave. Understanding PATH, export, and shell startup files makes everything click into place.

Every time you open a terminal, the shell sets up an environment before you type a single command. That environment contains variables — key-value pairs that control how the shell and the programs you run behave. Understanding this is essential for making your shell work the way you want it to.

What is an environment variable?

An environment variable is a named value available to the current shell and any process it starts. Programs read these values to configure their behaviour.

Print all current environment variables:

env

Print a specific one:

echo $HOME
echo $USER
echo $SHELL

Common built-in variables:

VariableContains
HOMEYour home directory path
USERYour username
SHELLPath to your login shell
PATHColon-separated list of directories to search for commands
PWDCurrent working directory
EDITORDefault text editor
LANGSystem language and locale

PATH

PATH is the most important environment variable for day to day use. When you type a command, the shell looks for an executable with that name in each directory listed in PATH, in order.

echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/home/jan/.local/bin

When you type ls, the shell finds /usr/bin/ls because /usr/bin is in PATH.

If a command is not in any PATH directory, you get "command not found".

Adding to PATH

To add a directory to PATH for the current session:

export PATH="$PATH:/home/jan/scripts"

This appends /home/jan/scripts to the existing PATH. Programs in that directory can now be run by name.

To make it permanent, add it to your shell config file (covered below).

Setting and exporting variables

Set a variable in the current shell:

MYVAR="hello"

This variable exists in the current shell but is not passed to child processes (programs you run). To make it available to child processes, export it:

export MYVAR="hello"

Now any program started from this shell will have MYVAR in its environment.

Set a variable for a single command only:

DEBUG=true ./my-script.sh

This sets DEBUG in the environment of that one command without affecting the current shell.

Unset a variable:

unset MYVAR

Shell startup files

This is where most confusion about environment variables comes from. Different files are sourced in different situations.

Login shells vs interactive shells

A login shell is what you get when you log in — via SSH, a virtual console, or su -. It reads login-specific config files.

An interactive shell is any shell where you type commands — your terminal emulator. It may or may not be a login shell.

A non-interactive shell runs scripts. It reads almost no config files.

The files

/etc/profile — system-wide config, sourced by all login shells. Do not edit this directly.

/etc/profile.d/*.sh — drop files here to add system-wide config. Cleaner than editing /etc/profile.

~/.bash_profile or ~/.profile — user login shell config. Sourced once on login. This is where you set PATH additions and environment variables that should be available everywhere.

~/.bashrc — user interactive shell config. Sourced every time you open a new terminal. This is where you put aliases, functions, and prompt customisation.

The typical pattern is to put environment variables in ~/.profile (or ~/.bash_profile) and source ~/.bashrc from there:

# In ~/.bash_profile
export PATH="$PATH:/home/jan/scripts"
export EDITOR=vim
 
# Source bashrc for interactive shell settings
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi
# In ~/.bashrc
alias ll='ls -la'
alias gs='git status'
 
# Custom prompt
PS1='\u@\h:\w\$ '

Reload after editing

After editing a config file, either open a new terminal or source the file manually:

source ~/.bashrc
# or
. ~/.bashrc

Practical examples

Persisting PATH changes

Add to ~/.profile:

export PATH="$PATH:/home/jan/.local/bin:/home/jan/scripts"

Setting a default editor

export EDITOR=vim
export VISUAL=vim

EDITOR is used by programs that open a simple line editor. VISUAL is for full-screen editors. Many programs check both.

Application configuration

Many applications read config from environment variables:

export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
export NODE_ENV=production
export DATABASE_URL=postgres://localhost/mydb

Keeping secrets out of scripts

Instead of hardcoding credentials in scripts:

#!/bin/bash
curl -H "Authorization: Bearer $API_TOKEN" https://api.example.com/data

Set API_TOKEN in your environment before running the script. Never hardcode secrets in scripts that might end up in version control.


The shell environment is the invisible layer underneath everything you do in the terminal. PATH determines what commands are available. Startup files determine what environment every new shell has. Getting these right once means you never have to fight your shell again.

Next up: log management — /var/log, journalctl filtering, and logrotate.

0 views