Environment variables & shell configuration
Shell vs environment variables, PATH, export, .bashrc vs .profile, aliases and a better prompt.
Every process carries a set of named values called environment variables: your home directory, your username, your language, and the all-important PATH that tells the shell where to find commands. Understanding them explains a lot of "it works in my terminal but not in cron/systemd/my script" mysteries. This lesson also shows how to customise Bash with ~/.bashrc.
Looking at variables#
env (or printenv) with no arguments lists every environment variable. Some you'll meet constantly:
Shell variables vs environment variables#
Creating a variable: no spaces around =.
greeting is a shell variable: it exists only inside this shell. The child process (bash -c) doesn't receive it. export promotes it to an environment variable, which is copied into every child:
Export only flows downwards: a child can never change its parent's variables. That's why cd inside a script doesn't move your terminal, and why you source files whose variables you want to keep.
Set a variable for one command only by putting it in front:
You'll see this pattern everywhere: LANG=C sort file, DEBUG=1 ./app, PORT=3000 npm start. unset greeting deletes a variable.
Quoting and expanding#
"$var"expands the variable but keeps it as one word, even if it contains spaces. Quote variables by habit.'$var'is literal text: no expansion.${var}separates the name from following text:echo "${name}_backup".
Handy expansions (more in the scripting lessons):
PATH: how commands are found#
(Yours will be longer.) When you type mytool, Bash checks each directory in order and runs the first mytool it finds. If none has it: command not found. The current directory is not in PATH (a deliberate security choice), which is why you run local scripts as ./script.sh.
Add your own directory, keeping the existing value:
Putting it first means your version wins over system ones; append ($PATH:$HOME/bin) if you want the opposite. Debian/Ubuntu's default ~/.profile already adds ~/bin and ~/.local/bin if they exist when you log in. pip install --user and many installers drop tools in ~/.local/bin.
Never write
export PATH=~/bin. You'll lose/usr/bin, and evenlsstops working in that terminal. (Fix: close the terminal, orexport PATH=/usr/local/bin:/usr/bin:/bin.)
Startup files: .bashrc vs .profile#
Bash reads different files depending on how it starts:
On Debian and Ubuntu, ~/.profile sources ~/.bashrc, so in practice:
- Put aliases, functions, prompt and shell options in
~/.bashrc. - Put environment variables that GUI apps and logins also need (like
PATH) in~/.profile. If you SSH in,~/.profile(or~/.bash_profile) runs.
On Fedora, the equivalent pair is ~/.bash_profile (which sources ~/.bashrc) and ~/.bashrc. If you create a ~/.bash_profile on Ubuntu, Bash stops reading ~/.profile, a classic surprise.
After editing, reload in the current shell:
System-wide variables can go in /etc/environment (plain KEY=value lines, no export) or a script in /etc/profile.d/.
Aliases and a nicer shell#
alias lists them all and unalias ll removes one. Run the original command, bypassing an alias, with a backslash: \rm file. For anything with arguments in the middle, write a function in ~/.bashrc instead:
A few ~/.bashrc lines worth adding:
In PS1, \u is the user, \h the host, \w the working directory, and \$ shows # for root.
History tricks#
Start a command with a space (with ignoreboth set) to keep it out of history, which is useful when a command contains a password you couldn't avoid typing.
Common mistakes#
- Spaces around
=:name = ashatries to run a command calledname. - Forgetting
export, then wondering why a program can't see the variable. - Overwriting
PATHinstead of extending it. - Expecting cron or systemd to load your
~/.bashrc. They don't: set variables in the crontab or unit file, and use absolute paths. - Storing secrets in
~/.bashrcthat then leak into every program you run. Use files with600permissions or a secrets manager.
What's next#
That completes the command-line power tools. Next you'll start running the system like an admin, beginning with package management: installing, updating and removing software with apt, dnf, Snap and Flatpak.
Check your understanding
Quick quiz
1.You run
greeting=hiand then start a script that prints$greeting. It prints nothing. Why?2.You put your own tools in
~/bin. Which line in~/.bashrclets you run them by name while keeping all the normal commands?3.You just added an alias to
~/.bashrc. How do you use it in the terminal you already have open?
Finished reading?
Mark this lesson complete to track your progress.