Terminal · foundation
Shell variables vs environment variables
A shell variable is state maintained by the shell, while an exported variable is included as a name-value environment entry for subsequently created child processes.
Why it matters
The distinction determines whether configuration reaches a program, stays local to one shell, or affects only one command invocation.
Mental model
How to reason about shell variables vs environment variables
The shell owns a variable table with export marks; when it launches a process, it constructs that child's initial environment from the exported entries.
Analogy
A shell variable is a note kept at your desk, while exporting it adds the note to the onboarding packet copied for each new worker you start.
Examples
See the boundary, not just the happy path
Worked example · Export for future children
API_URL=https://api.example.test; export API_URLThe assignment creates or updates a shell variable, and export marks it for inclusion in environments of commands launched afterward.
Worked example · One-command environment
PORT=8080 node server.jsThe assignment prefix places PORT in node's environment for this invocation without permanently exporting PORT from the calling shell.
Useful contrast · Unexported shell state
unset MODE; MODE=debug; sh -c 'printf "%s\n" "$MODE"'After unset clears any prior value and export attribute, the unexported assignment remains parent-shell state and the child sh does not receive MODE.
Common mistakes
Misconceptions to remove early
Adding spaces around the assignment equals sign
In POSIX-like shells, NAME=value is assignment syntax; NAME = value is parsed as a command named NAME with separate arguments.
Assuming environment variables are private secret storage
They are a configuration transport with platform-dependent exposure to child processes, diagnostics, and privileged inspection, not an encrypted vault.
Quick check
Can you predict the result?
1. Which form sets DEBUG only in the environment of the invoked test command?
- • DEBUG=1 ./test
- • export DEBUG=1; ./test
- • DEBUG = 1 ./test
2. Does changing an exported variable update a child process that is already running?
Keep building