Skip to content
DevOps devops linux 5 min read

Environment Variables & PATH

An environment variable is a named value that the shell (the program that runs your commands) and other programs can read while they run. Think of it as a sticky note that says “DATABASE_URL is this” or “my editor is nano” that any program can look at. Environment variables are how Linux passes settings and secrets to programs without hard-coding them, and the most important one of all, PATH, is what lets you type git instead of /usr/bin/git. Getting comfortable with them is essential for DevOps, because deploying apps, configuring services, and running scripts all depend on the right variables being set.

What an environment variable looks like

A variable has a name (by convention written in UPPERCASE) and a value (always text). Programs read these values to decide how to behave. For example, the LANG variable tells programs your language and character set, and HOME points to your home directory.

To read a single variable, use echo with a $ in front of the name. The $ tells the shell “substitute the value of this variable here.”

echo $HOME
echo $USER
echo $SHELL

Output:

/home/devops
devops
/bin/bash

To see all environment variables currently set, use the env command (or printenv).

env | sort | head -8

Output:

HOME=/home/devops
LANG=en_US.UTF-8
LOGNAME=devops
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/home/devops
SHELL=/bin/bash
TERM=xterm-256color
USER=devops

Tip: Curly braces make the variable name unambiguous. echo "${USER}_backup" prints devops_backup, but echo "$USER_backup" looks for a variable named USER_backup (which is empty). Use ${VAR} whenever the variable is touching other text.

Setting a variable: session vs. persistent

There are two completely different scopes for a variable, and mixing them up is the most common beginner mistake.

ScopeHow you set itHow long it lastsWhen to use
Shell-only (local)NAME=valueUntil you close the terminal; only this shell sees itQuick, throwaway values used in the current session
Session (exported)export NAME=valueUntil you close the terminal; child programs see it tooPassing a value to a command or script you’re about to run
Persistent (per user)Add export to ~/.bashrcEvery new login shell for that userYour personal defaults (editor, PATH additions)
Persistent (all users)Add to /etc/environmentEvery login for every userSystem-wide settings on a server

Local vs. exported in the same session

A plain assignment is only visible to the shell itself. To make it visible to programs the shell launches (its “child processes”), you must export it.

MYVAR=hello
echo $MYVAR
bash -c 'echo "child sees: $MYVAR"'
export MYVAR
bash -c 'echo "child sees: $MYVAR"'

Output:

hello
child sees:
child sees: hello

Notice the first child saw nothing because MYVAR was not exported. After export, the child process inherited it. This matters when running scripts or starting services: if your app reads a variable but you forgot to export it, the app sees an empty value.

To remove a variable, use unset:

unset MYVAR

Making variables persistent

Session variables vanish when you log out. To keep them, write them into a startup file that the shell reads automatically.

Per-user: ~/.bashrc

The file ~/.bashrc runs every time you open an interactive Bash shell. Edit it with a text editor:

nano ~/.bashrc

Add a line at the bottom:

export EDITOR=nano
export PROJECT_HOME="$HOME/projects"

Save and exit. The change does not apply to your current shell until you re-read the file (or open a new terminal):

source ~/.bashrc
echo $EDITOR

Output:

nano

source (or its shorthand .) runs the file in your current shell so the new variables take effect immediately, without logging out.

System-wide: /etc/environment

/etc/environment sets variables for every user on the machine. It is read at login by the system, before any shell starts. Note it is not a shell script: you write plain KEY=value lines with no export keyword and no shell syntax.

sudo nano /etc/environment
JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
APP_ENV=production

These apply to new logins. Run source /etc/environment to load them into your current session, or log out and back in.

Security gotcha: Never put secrets (passwords, API keys, database credentials) in ~/.bashrc or /etc/environment on a shared server. They are readable by processes and can leak into logs or env dumps. For app secrets, use a dedicated secrets manager or a tightly permissioned .env file (chmod 600) loaded only by the app.

Understanding PATH

PATH is the single most important environment variable. It is a list of directories, separated by colons, that the shell searches when you type a command name. When you type git, the shell does not scan your whole disk. It walks through each directory in PATH, left to right, and runs the first git it finds.

echo $PATH

Output:

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

To find out which file actually runs for a command name, use which:

which python3
which ls

Output:

/usr/bin/python3
/usr/bin/ls

This is why a freshly installed program sometimes gives “command not found”: its directory is not in PATH. The fix is to add that directory.

Adding a directory to PATH

Suppose you installed a tool into ~/.local/bin (a common location for user-installed binaries). Add it to PATH by prepending it, keeping the existing PATH on the end:

export PATH="$HOME/.local/bin:$PATH"

Putting your directory first means your version wins if a command exists in two places. To make this permanent, add the same line to ~/.bashrc and source it. Verify the change:

echo $PATH | tr ':' '\n' | head -3

Output:

/home/devops/.local/bin
/usr/local/sbin
/usr/local/bin

Gotcha: Always include :$PATH when extending PATH. If you write export PATH="$HOME/.local/bin" you wipe out every existing directory, and suddenly even ls and sudo stop working in that shell. If that happens, just close the terminal and open a new one.

Best Practices

  • Use export whenever a program or script needs to read the variable; a plain assignment stays inside the shell only.
  • Keep personal defaults in ~/.bashrc and machine-wide settings in /etc/environment; do not duplicate the same variable in both.
  • Always extend PATH with export PATH="new/dir:$PATH" so you never erase the existing directories.
  • Never store secrets in shell startup files on shared servers; use a secrets manager or a chmod 600 .env file.
  • After editing a startup file, run source ~/.bashrc to apply changes immediately instead of opening a new terminal.
  • Use UPPERCASE names for environment variables and ${VAR} braces when the name sits next to other text.
  • Use which <command> to debug “command not found” errors, then add the missing directory to PATH.
Last updated June 15, 2026
Was this helpful?