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_URL

The 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.js

The 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
Answer: DEBUG=1 ./test
2. Does changing an exported variable update a child process that is already running?
Answer: No; a child receives its initial environment when it is created and does not share the parent's variable table.

Keep building

Authoritative references

Make the idea retrievable.

Study this concept with spaced repetition, next to the commands where you use it.

Get Terminaster