Free — no signup required

Shell Config: .bashrc, .zshrc, and the Login Shell

3 min read

The Startup Script

Every time you open a new terminal, the shell runs a configuration file before presenting you with a prompt. This file is where you customize your environment — defining shortcuts, setting environment variables, and configuring your prompt.

Which file does my shell use?

Shell Interactive config file Login shell config file
Bash ~/.bashrc ~/.bash_profile
Zsh ~/.zshrc ~/.zprofile

The distinction between login and interactive shells trips up many engineers, and understanding why it exists is more useful than memorizing which file is which. A login shell is what you get when you're establishing a brand-new session — SSHing into a server, or logging into a text console. It's meant to build the entire environment for that session from scratch: PATH, locale, and other variables every program launched afterward will inherit. An interactive, non-login shell is what you get when you open a new terminal tab on a machine where a session already exists — the environment your login shell already set up is still in effect, so this new shell doesn't need to redo that work. Bash and Zsh route these two cases to different config files precisely because they represent different amounts of setup.

There's a subtlety that explains why the two files often need to cooperate: exported environment variables are inherited by every child process, but aliases and shell functions are not — they live only inside the shell process that defines them, not in the process environment the kernel hands down to children. That means an alias defined only in the login config won't exist in a later interactive shell, and vice versa. The common fix is to have the login config file source the interactive one, so a single set of definitions covers both cases regardless of which kind of shell you end up in.

Aliases — shortcuts for long commands

An alias binds a short name to a longer command as a shell-level substitution: type the short name, and the shell swaps in the full command before running it. This is how a frequently-typed, multi-flag command becomes a two-letter habit. Because aliases live only in the interactive shell that defines them, they're the canonical example of something that belongs in the interactive config file rather than the login-only one.

Environment variables

Environment variables are key-value pairs that any program can read at startup to configure its own behavior without the caller hardcoding anything — which editor to launch, for instance, is something other tools read from a variable rather than being told directly every time. Marking a variable for export is what makes it visible to child processes launched from that shell; a variable set without exporting stays private to the shell itself, invisible to anything it launches.

Applying changes without restarting

Editing a config file only affects new shells that read it from that point on — a shell that already started keeps whatever it loaded at startup. Re-reading the file into the current shell process, without starting a new one, is what lets a change take effect immediately instead of waiting for your next terminal tab or SSH session.

$PATH — how the shell finds commands

When you type a command name, the shell doesn't search the whole filesystem for it. It searches only the directories listed in $PATH, in order, and runs the first matching executable it finds. This is why a freshly installed tool sometimes reports as not found even though the file clearly exists on disk: its directory simply isn't among the ones the shell has been told to search, and the fix is always the same — add that directory to $PATH in whichever config file is appropriate for how your shells get started.

This is one of 18 chapters

Every chapter is free — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

Sign up free