thecodingidiot.com

The TerminalThe Shell's Memory

The Shell's Memory

The shell maintains a set of named values that every process it spawns can read. These are environment variables[1]. They are how the shell knows where to find programs, what your username is, and what terminal you are using. They are also how you configure tools and pass information between processes.

What is in the environment

env             # print all environment variables
printenv        # same, slightly different format
printenv HOME   # print a specific variable
echo $HOME      # the shell expands $HOME to its value

Some important ones you already have:

echo $HOME      # your home directory: /home/user
echo $USER      # your username: user
echo $SHELL     # your shell: /bin/bash
echo $PWD       # current directory (same as pwd)

PATH

$PATH is the most important environment variable. It is a colon-separated list of directories. When you type gcc and press Enter, the shell searches each directory in $PATH in order, looking for a program named gcc. If it finds one, it runs it. If it does not, you get command not found.

echo $PATH

You will see something like:

/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin

To add a directory to $PATH:

export PATH="$HOME/.local/bin:$PATH"

This prepends ~/.local/bin to the existing $PATH. Now the shell will check there first. Programs you install locally go in ~/.local/bin and become available without root.

In c05/03 you implement this search in C — getenv("PATH"), split on :, and access() to test each candidate executable.

Setting variables

MY_VAR="hello"      # sets a shell variable
echo $MY_VAR        # prints: hello

This sets a shell variable — it exists in the current shell but is not passed to child processes[2].

export MY_VAR="hello"    # sets and exports to child processes

export marks the variable so that any process this shell spawns will inherit it. Without export, MY_VAR is invisible to programs you run.

unset MY_VAR        # remove the variable entirely

Making it permanent

Variables set in the terminal exist only for the current session. Close the terminal and they are gone. To make them permanent, add them to ~/.bashrc:

echo 'export MY_VAR="hello"' >> ~/.bashrc
source ~/.bashrc

~/.bashrc is a shell script that Bash runs every time a new interactive shell starts. source runs it in the current shell without starting a new one — so your changes take effect immediately.

source ~/.bashrc    # reload bashrc in the current session

There is a distinction worth knowing: ~/.bashrc runs for interactive non-login shells — the terminals you open during a normal session. ~/.bash_profile (or ~/.profile on systems that use it) runs for login shells — SSH sessions, virtual consoles, and some terminal emulators on first launch. If you add an export to ~/.bashrc and it does not appear in an SSH session, this is why. The safe fix is to source ~/.bashrc from ~/.bash_profile if it exists, which most default configurations already do.

A practical use

Programs can read environment variables the same way the shell does. A common pattern in C programs: a variable that switches behavior — extra output, verbose logging, debug[3] mode. To set one for a single run without exporting it:

DEBUG=1 ./myprogram

VAR=value command sets the variable only for that invocation. The process inherits it; your shell does not. The moment the program exits, it is gone. This is the right way to change behavior for one run without polluting your environment.

To make it permanent for the current session:

export DEBUG=1

To make it permanent across sessions, add it to ~/.bashrc:

echo 'export DEBUG=1' >> ~/.bashrc
source ~/.bashrc

The programs you write in the C chapters ahead will read variables like this — checking getenv("DEBUG") in C to decide whether to print extra information. This page is why that works.

Footnotes

  1. Environment variable - Wikipedia

  2. Child process - Wikipedia

  3. Debugging - Wikipedia