Linux: Environment Variables and PATH

Environment variables are key-value pairs the operating system uses to store configuration. They determine where the Shell looks for commands (PATH), what language to use (LANG), and which editor to use (EDITOR).

📋 Prerequisites: You should first complete

1. What You Will Learn


2. A "command not found" Story

(1) The Pain: Installed a Program But Can't Find It

Alex installed the Python tool httpie with pip install --user, but typing http gave:

BASH
http example.com
# Command 'http' not found

Alex was confused: "I installed it, why can't the system find it?"

(2) PATH — Telling the Shell Where to Find Programs

Bob explained: "The program is installed, but the Shell doesn't know where to look. The PATH environment variable is the Shell's 'treasure map.'"

BASH
echo $PATH
# /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# ~/.local/bin is not in PATH, so the Shell can't find http
ls ~/.local/bin/http*
# /home/charlie/.local/bin/http

# Add ~/.local/bin to PATH
export PATH="$PATH:$HOME/.local/bin"
http example.com    # Now it works

(3) The Benefit: Understanding the Mechanism Behind Everything

Alex learned that putting export PATH="$PATH:~/bin" in .bashrc makes it permanent. Now whenever he installs a new tool, he knows to check if the installation directory is in PATH.


3. Knowledge Points

(1) What Are Environment Variables

Environment variables are key-value pairs stored in the operating system that all child processes inherit.

TEXT
# View all environment variables
printenv

# View individual variables
echo $HOME
echo $USER
echo $SHELL
echo $LANG
echo $PWD

Common environment variables:

Variable Meaning Typical value
HOME Current user's home directory /home/alice
USER Current username alice
SHELL Current Shell path /bin/bash
PATH Command search path /usr/bin:/bin:/usr/local/bin
LANG Language and encoding en_US.UTF-8
PWD Current working directory /home/alice/projects
OLDPWD Previous working directory /etc
EDITOR Default editor vim

(2) PATH — Command Search Path

When you type ls, the Shell searches for the ls program in each directory listed in PATH, in order. If found, it executes; if not, it reports command not found.

💡 Tip: PATH works by "sequential search" — the Shell looks through PATH directories from left to right and stops at the first match. Directories earlier in PATH have higher priority. If a newly installed program doesn't seem to work, an older version might be in an earlier PATH directory.

BASH
# View current PATH
echo $PATH
# /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# Find which directory a command is in
which ls
# /usr/bin/ls

# View all possible locations for a command (including aliases and functions)
type ls
# ls is aliased to `ls --color=auto'

(3) Setting and Unsetting Environment Variables

BASH
# Temporary setting (only effective in current Shell)
MY_VAR="hello"

# Export as environment variable (child processes can access it)
export MY_VAR="hello"

# Set and export in one command
export MY_VAR="hello"

# Unset an environment variable
unset MY_VAR

# Temporarily set for a single command (without polluting current environment)
LANG=ja_JP.UTF-8 date

(4) Shell Configuration File Loading Order

Understanding the loading order is important — it explains why sometimes changes to ~/.bashrc don't take effect:

BASH

Login Shell (SSH login, tty login):
    /etc/profile
    ~/.bash_profile   (if it exists, the following two are skipped)
    ~/.bash_login
    ~/.profile

Non-login Shell (opening a new terminal):
    /etc/bash.bashrc
    ~/.bashrc

ℹ️ Note: .bashrc and .profile load at different times — SSH login loads .profile, while opening a new terminal loads .bashrc. The best practice is to add source ~/.bashrc in .profile and put all configuration in .bashrc, so it works regardless of how you log in.

Best practice: Add this to .bash_profile:

BASH
if [ -f ~/.bashrc ]; then
    source ~/.bashrc
fi

Then put all custom configuration in .bashrc.

(5) ▶ Example: View and Set Environment Variables

BASH
# View environment variables
echo "My home directory is: $HOME"
echo "Current user: $USER"
echo "My Shell: $SHELL"

# Set a temporary variable
export GREETING="Hello from Linux"
echo $GREETING

# Open a new terminal window and check if $GREETING is still there
# Answer: No — temporary variables only exist in the current Shell

Output:

TEXT
My home directory is: /home/alice
Current user: alice
My Shell: /bin/bash
Hello from Linux

(6) ▶ Example: Understanding PATH

BASH
# View current PATH
echo $PATH | tr ':' '\n'    # Display one path per line

# Find which directory ls is loaded from
which ls
# /usr/bin/ls

# What happens if PATH is wrong?
PATH=""      # Clear PATH (dangerous!)
ls
# bash: ls: No such file or directory

# Restore PATH
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

Output:

TEXT
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/bin/ls

(7) ▶ Example: Add ~/scripts to PATH (Permanent)

BASH
# Create your own scripts directory
mkdir -p ~/scripts

# Add ~/scripts to PATH (write to .bashrc)
echo 'export PATH="$PATH:$HOME/scripts"' >> ~/.bashrc

> 💡 Tip: To make environment variables permanent, you must write the `export` command to `~/.bashrc` (or `~/.profile`). After modifying, run `source ~/.bashrc` to apply immediately; otherwise the new configuration will only load in newly opened terminals.

# Reload
source ~/.bashrc

# Verify
echo $PATH | tr ':' '\n' | grep scripts
# /home/alice/scripts

Output:

TEXT
/home/alice/scripts

(8) ▶ Example: Common Development Environment Variable Configuration

BASH
# Add the following to ~/.bashrc

# Default editor
export EDITOR=vim

# Locale
export LANG=en_US.UTF-8

# Python development
export PYTHONSTARTUP=~/.pythonrc    # Python interactive startup script
export PIP_REQUIRE_VIRTUALENV=true  # pip requires virtual environment

# Node.js development
export NODE_ENV=development
export npm_config_prefix=~/.npm-global

# Go development
export GOPATH=$HOME/go
export PATH="$PATH:$GOPATH/bin"

# Your own scripts
export PATH="$PATH:$HOME/scripts"
export PATH="$PATH:$HOME/.local/bin"

Output:

TEXT
EDITOR=vim
LANG=en_US.UTF-8
PYTHONSTARTUP=/home/alice/.pythonrc
PIP_REQUIRE_VIRTUALENV=true
NODE_ENV=development
GOPATH=/home/alice/go

(9) ▶ Example: Check If a Command Can Be Found

BASH
# Use which to find the command path
which python3
# /usr/bin/python3

# Use type to check command type (alias/function/builtin/external)
type ls
# ls is an alias for `ls --color=auto'
type cd
# cd is a shell builtin
type node
# node is /usr/bin/node

# Use command -v (most reliable method)
command -v python3
# /usr/bin/python3

Output:

TEXT
/usr/bin/python3
ls is an alias for `ls --color=auto'
cd is a shell builtin
node is /usr/bin/node
/usr/bin/python3

(10) ▶ Comprehensive Example: Debugging a "command not found" Problem

BASH
#!/bin/bash
# debug-path.sh - Debug command-not-found issues

CMD="${1:-http}"

echo "=== 1. What is the command ==="
type "$CMD" 2>/dev/null || echo "type: $CMD not found"

echo ""
echo "=== 2. Which PATH directories contain this command ==="
IFS=':' read -ra PATHS <<< "$PATH"
for dir in "${PATHS[@]}"; do
    if [ -f "$dir/$CMD" ]; then
        echo "Found: $dir/$CMD"
    fi
done

echo ""
echo "=== 3. Global search with find ==="
find /usr /opt $HOME -name "$CMD" -type f 2>/dev/null | head -5

echo ""
echo "=== 4. If found but not in PATH ==="
echo "Run: export PATH=\"\$PATH:/found/directory\""

❓ FAQ

Q: Does PATH order matter? A: Very much! The Shell searches PATH directories in order and stops at the first match. If /usr/local/bin comes first, it takes priority over /usr/bin. This is why newly installed programs sometimes still run an older version — check your PATH order.

Q: Will environment variables disappear after a reboot? A: Temporary variables set with export will be lost after a reboot. To persist them, write the export commands to a Shell configuration file (~/.bashrc or ~/.bash_profile).

Q: Which executes first, .bashrc or .bash_profile? A: Login Shell: /etc/profile~/.bash_profile~/.bash_login~/.profile (if previous files don't exist). Non-login Shell: /etc/bash.bashrc~/.bashrc.

Q: How do I set global environment variables (for all users)? A: Write to /etc/environment (simple key-value pairs, no scripting) or /etc/profile.d/custom.sh (supports Shell syntax, requires root privileges).

Q: What's the difference between printenv and set? A: printenv only shows environment variables (exported ones). set shows all variables including Shell local variables and functions. Use printenv for a complete environment view, set for script debugging.


📖 Summary


📝 Exercises

  1. Basic (Difficulty ⭐): View the current PATH (use tr ':' '\n' for clearer line-by-line display), and use which python3 and type cd to understand command types
  2. Intermediate (Difficulty ⭐⭐): Create a ~/scripts directory, write a simple hello.sh script, add it to PATH and run it directly; set EDITOR=vim (or nano) in .bashrc and verify with source
  3. Advanced (Difficulty ⭐⭐⭐): Write a debug-path.sh script that takes a command name as an argument and automatically checks whether it's in PATH, which directory contains it, and suggests a fix if it's not in PATH
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏