Shell Environment Variables: export, env, .bashrc, .bash_profile

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 export is needed
  • Explain the startup file load order for login and non-login shells
  • Use .bashrc and .bash_profile correctly 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 set and env
  • [ ] Edited .bashrc and applied it immediately with source
  • [ ] 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.

Next Reading