Environment Variables

Environment variables configure how your shell and programs behave. PATH tells the shell where to find commands. HOME points to your home directory. Your apps read database URLs and API keys from them.

View Environment Variables

Terminal
$# All variables
$env
USER=john HOME=/home/john PATH=/usr/local/bin:/usr/bin:/bin SHELL=/bin/bash ...
$
$# Specific variable
$echo $PATH
/usr/local/bin:/usr/bin:/bin
$
$# Or use printenv
$printenv HOME
/home/john

Common Variables

VariablePurpose
PATHDirectories to search for commands
HOMEUser's home directory
USERCurrent username
SHELLDefault shell
EDITORDefault text editor
LANGLanguage/locale setting
PWDCurrent directory

Set Variables

Terminal
$# For current session only
$MY_VAR="hello"
$echo $MY_VAR
hello
$
$# Make available to child processes
$export MY_VAR="hello"
$bash -c 'echo $MY_VAR'
hello

Without export, variables are local to the current shell.

Persistent Variables

For Your User: ~/.bashrc

Terminal
$nano ~/.bashrc

Add:

hljs bash
export EDITOR=vim
export PATH="$HOME/bin:$PATH"
export API_KEY="your-key-here"

Then reload:

Terminal
$source ~/.bashrc
$# Or
$. ~/.bashrc

Shell Configuration Files

FileWhen Loaded
~/.bashrcInteractive non-login shells
~/.bash_profileLogin shells
~/.profileLogin shells (if no .bash_profile)
/etc/environmentSystem-wide, all users
/etc/profileSystem-wide, login shells

Which File to Use?

For most cases, use ~/.bashrc. For system-wide variables, use /etc/environment.

Modify PATH

Terminal
$# Add directory to beginning (searched first)
$export PATH="/opt/myapp/bin:$PATH"
$
$# Add to end
$export PATH="$PATH:/opt/myapp/bin"

Add to ~/.bashrc to make permanent:

hljs bash
# Add custom bin directories
export PATH="$HOME/bin:$HOME/.local/bin:$PATH"

Per-Command Variables

Terminal
$# Set just for one command
$DATABASE_URL=postgres://localhost/test ./migrate.sh
$
$# Multiple variables
$NODE_ENV=production PORT=3000 node server.js

Variable is only set for that command, doesn't affect your shell.

Using .env Files

Common pattern for applications:

hljs bash
# .env file
DATABASE_URL=postgres://localhost/mydb
API_KEY=secret123
DEBUG=true

Load it:

Terminal
$# In bash
$export $(cat .env | xargs)
$
$# Or source with set -a
$set -a && source .env && set +a

Don't Commit .env

Add .env to .gitignore. Never commit secrets to git.

Check If Variable Is Set

hljs bash
#!/bin/bash

# Check if set
if [[ -z "$API_KEY" ]]; then
    echo "API_KEY is not set"
    exit 1
fi

# Use default if not set
DB_HOST="${DB_HOST:-localhost}"

Unset Variables

Terminal
$export MY_VAR="something"
$echo $MY_VAR
something
$unset MY_VAR
$echo $MY_VAR
(empty)
Knowledge Check

What's the difference between 'VAR=x' and 'export VAR=x'?

Quick Reference

CommandPurpose
echo $VARView variable
envList all variables
export VAR=valueSet and export
unset VARRemove variable
source ~/.bashrcReload config
printenv VARPrint variable value

Key Takeaways

  • export makes variables available to child processes
  • Add to ~/.bashrc for persistence
  • PATH controls where commands are found
  • Use .env files for application config (don't commit them)
  • source reloads configuration files
  • Check required variables at script start

Next: creating shell aliases.