|
Environment variables are key-value pairs available to every program running on your system. They store configuration like your username, home directory, and current working directory. Access any environment variable by prefixing its name
with |
|
|
Output:
Your username: Your home directory: /root Current directory: /tmp |
|
|
There are two kinds of variables in the shell: shell variables and environment variables. Understanding the difference is essential. A shell variable exists only in the current shell. If you start a child process, it cannot see the variable. An environment variable is inherited by child processes.
The |
|
|
Output:
Parent sees SECRET: I am local Child sees SECRET: <not visible> After export: Parent sees SECRET: I am local Child sees SECRET: I am local |
|
|
There are several ways to create and export variables. Each approach has slightly different behavior.
The key test: can a child process see the variable? Only exported variables are inherited by children. |
|
|
Output:
Method 1 - shell variable: Parent: DB_NAME=mydb Child: DB_NAME=<not visible> Method 2 - export in one step: Parent: DB_HOST=localhost Child: DB_HOST=localhost Method 3 - export on a separate line: Parent: DB_PORT=5432 Child: DB_PORT=5432 |
|
|
The system and shell set several standard environment variables. Knowing these helps you write portable scripts that adapt to the user’s environment.
|
|
|
Output:
USER: HOME: /root PWD: /tmp PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin SHELL: TERM: LANG: |
|
|
Scripts often need to check whether a variable is set and provide fallback values. The shell offers two approaches: test flags and parameter expansion. Test flags:
Parameter expansion provides four forms:
|
|
|
Output:
Checking with test flags:
HOME is set to: /root
UNDEFINED_VAR is not set
Fallback values with ${VAR:-default}:
DB_HOST: localhost
DB_PORT: 5432
Assign defaults with ${VAR:=default}:
CACHE_DIR is now: /tmp/cache
Alternate values with ${VAR:+alternate}:
USER is set:
MISSING is set:
${VAR:?message} exits if VAR is unset (commented out above)
|
|
|
Sometimes you need a variable only for a single command or the current session, without permanently changing the environment. Three approaches:
|
|
|
Output:
Inline assignment (VAR=value command): During: GREETING=Hola After: GREETING=<gone> Using env: During: COLOR=blue After: COLOR=<gone> Modifying PATH temporarily: PATH has 6 entries After prepend, PATH starts with: /root/bin |
|
|
To remove a variable from the environment, use These tools are useful for testing, debugging, and isolating programs from the surrounding environment. |
|
|
Output:
Before unset: TEMP_VAR=temporary After unset: TEMP_VAR=<removed> Exported variables (first 5): FAKETIME=2025-01-01 10:00:00 FAKETIME_NO_CACHE=1 FAKETIME_SHARED=/faketime_sem_1 /faketime_shm_1 HOME=/root HOSTNAME=shellbyexample Clean environment with env -i: Variables in clean env: 3 PATH is set: yes USER is set: <not set> |
|
|
A common pattern in real applications is loading
configuration from a By default, sourced variables are shell-only. To make
them environment variables (visible to child processes),
use |
|
|
Output:
Without set -a: Parent sees APP_HOST: 0.0.0.0 Child sees APP_HOST: <not visible> With set -a: Parent sees APP_HOST: 0.0.0.0 Child sees APP_HOST: 0.0.0.0 Config function with defaults: APP_PORT=3000 APP_HOST=0.0.0.0 APP_DEBUG=false Overridden via inline variables: APP_PORT=8080 APP_HOST=0.0.0.0 APP_DEBUG=true |
|
|
Bash
Bash provides built-in commands for inspecting and controlling variable attributes that aren’t available in POSIX sh.
These are useful for debugging and for protecting critical variables from accidental modification. |
|
|
Output:
Read-only export: APP_VERSION=1.0.0 All exported variables (first 5): declare -rx APP_VERSION="1.0.0" declare -x FAKETIME="2025-01-01 10:00:00" declare -x FAKETIME_NO_CACHE="1" declare -x FAKETIME_SHARED="/faketime_sem_1 /faketime_shm_1" declare -x HOME="/root" Inspecting APP_VERSION: declare -rx APP_VERSION="1.0.0" Inspecting HOME: declare -x HOME="/root" |
|
|
Environment variables are convenient for configuration, but they are a poor choice for storing secrets like API keys, passwords, and tokens. Why? Because environment variables are:
A safer alternative is storing secrets in files with restricted permissions, and reading them when needed. |
|
|
Output:
Child process can see the secret: API_KEY=secret123 Storing a secret in a file instead: Permissions: -rw------- Secret read from file: my_secret_token Cleaned up secret file |
|