Shell Environment Variables: export, env, .bashrc, .bash_profile
What You Will Achieve
- Explain shell vs environment variables from the child-process inheritance perspective
- Understand precisely why
exportis needed - Explain the startup file load order for login and non-login shells
- Use
.bashrcand.bash_profilecorrectly for their purposes - Diagnose why configuration changes are not applied
This is the core of LPIC-1 objective 105.1 "Customize and use the shell environment". The key points are the environment variable inheritance model and startup file load order.
Deciding Between Shell and Environment Variables
| Aspect | Shell variable | Environment variable |
|---|---|---|
| How to set | VAR=value |
export VAR=value |
| Inherited by children | No | Yes |
| List | set |
env / printenv |
| Use | Temporary value within the current shell | Config passed to children (e.g. PATH) |
If you need to pass a value to a child process (a command or script you run), make it an environment variable with export. For a temporary computation inside the shell only, a shell variable is enough.
Startup File Load Order
| Shell type | Files loaded |
|---|---|
| Login shell | /etc/profile → ~/.bash_profile (or ~/.bash_login → ~/.profile) |
| Non-login interactive shell | /etc/bash.bashrc → ~/.bashrc |
| Non-interactive shell (script) | The file pointed to by $BASH_ENV (usually none) |
By convention, ~/.bash_profile sources ~/.bashrc so configuration is consolidated in ~/.bashrc. Without knowing this, you cannot explain "it applies on SSH login but not when opening a terminal (or vice versa)".
Steps
Step 1: Set a shell variable and check inheritance
MYVAR=hello echo $MYVAR bash -c 'echo "child sees: $MYVAR"'
hello child sees:
MYVAR is a shell variable, so it is not inherited by the child process (bash -c) and is empty. This is the decisive difference from an environment variable.
Step 2: Promote to an environment variable with export
export MYVAR bash -c 'echo "child sees: $MYVAR"' export GREETING=hi env | grep GREETING
child sees: hello GREETING=hi
Promoting a shell variable to an environment variable with export makes it inherited by children. export VAR=value sets and promotes at once.
Step 3: Check the variable list
set | grep MYVAR env | grep MYVAR printenv PATH
MYVAR=hello MYVAR=hello /usr/local/bin:/usr/bin:/bin
set shows all variables including shell variables, while env (printenv) shows only environment variables. Appearing in both means it is exported; appearing only in set means it is still a shell variable.
Step 4: Edit a startup file and apply it
echo 'export EDITOR=vim' >> ~/.bashrc echo "alias ll='ls -alF'" >> ~/.bashrc source ~/.bashrc echo $EDITOR
vim
Appends to .bashrc take effect from a new shell. To apply immediately to the current shell, run source ~/.bashrc (equivalent to . ~/.bashrc).
Step 5: Delete variables
unset MYVAR echo "[$MYVAR]" unalias ll
[]
unset deletes a variable. Aliases are removed with unalias. To run a command temporarily without an environment variable, you can also use env -u VAR command.
Why export Is Needed
Linux processes create children via fork + exec. At that point only the parent's "environment" is copied to the child; shell variables are not passed to the child's memory space. export gives a variable the "export as environment" attribute, so it becomes part of the child's environment at exec time.
PATH and LANG are valid in children because they are environment variables already exported at login. Conversely, a non-exported shell variable cannot be referenced from a script because the script is launched as a child process and inherits the environment under this model. Inheritance is one-way parent→child; an environment variable changed in the child never propagates back to the parent.
Troubleshooting
Symptom: .bashrc changes not applied on SSH login
Cause: SSH login is a login shell, so ~/.bash_profile is read, not ~/.bashrc
Check:
grep bashrc ~/.bash_profile
Fix: Add [ -f ~/.bashrc ] && . ~/.bashrc to ~/.bash_profile and consolidate configuration in ~/.bashrc.
Symptom: A variable is not visible from a script
Cause: It is still a shell variable and not exported
Check:
export -p | grep VAR
Fix: Promote variables passed to a child (script) to environment variables with export VAR.
Symptom: A variable is not applied without source
Cause: An append to a startup file only takes effect from a new shell
Check:
echo $EDITOR
Fix: To apply immediately to the current shell, run source ~/.bashrc. It also applies when opening a new terminal.
Completion Checklist
- [ ] Confirmed shell variables are not inherited by child processes
- [ ] Confirmed inheritance by children after
export - [ ] Confirmed the display difference between
setandenv - [ ] Edited
.bashrcand applied it immediately withsource - [ ] Deleted a variable with
unset
Summary
| Scenario | Command | Purpose |
|---|---|---|
| Shell variable | VAR=value |
Temporary value within the current shell |
| Promote | export VAR |
Inherit to children |
| List (environment) | env / printenv |
Inspect environment variables |
| List (all) | set |
Includes shell variables |
| Apply now | source ~/.bashrc |
Reload startup file |
The environment variable model is directly tied to understanding process inheritance. Next, move to process priority control to connect operational knowledge.