Color Theme

Bash Startup Files

Written to remember occasionally helpful technical details.

I’ve had to look up the difference between ~/.bash_profile and ~/.bashrc one too many times, so I’m writing it out to bolster my memory and understanding. These files allow a user to customize which commands are run when a Bash shell starts up. While they can contain any command, they are mostly used to set up environment variables, aliases, completions, and prompts.

For reference, see the Bash manual entry on startup behavior.

The first thing to understand is that there are four different types of shells.

  • interactive login
  • noninteractive login
  • interactive non-login
  • noninteractive non-login

Since Bash sources the same startup files for both types of “login” shells, we’ll refer to them together as “login shells” for simplicity. Note that “sourcing” a file just means to execute the commands within that file. The term is derived from Bash’s source command (sometimes aliased as .).

For login shells, Bash sources /etc/profile and then ~/.bash_profile at startup.

For interactive non-login shells, Bash sources ~/.bashrc at startup.

For noninteractive non-login shells, Bash sources the filepath stored in $BASH_ENV at startup if that variable has been set.

Simple right? Unfortunately that’s not the whole story. While Bash always follows the above logic, the commands inside these files will differ depending on your environment. Operating systems distribute different versions of these files which themselves source other files. Sometimes those source commands are nested within conditional blocks that are evaluated at runtime. The effect is that beyond what is listed above, the files that get sourced during shell startup will not be consistent across all uses of Bash.

Environment Variables

A quick note on environment variables. Variables exported in files only sourced during login shell startup are still set in non-login shells (unless explicitly unset). This is because export causes variables to be passed to subsequent commands. A non-login shell is started by a command that runs in a process that is a descendant of the login shell’s process and thus inherits the latter’s exported variables.

Example Startup Sequence

To better understand the explanation above, let’s visualize the defaults provided in Fedora Linux.

Login Shells

Bash sources /etc/profile
	which sources
		/etc/profile.d/*.sh and
		/etc/profile.d/sh.local and
		/etc/bashrc
			which sources /etc/profile.d/*.sh (are these files being doubly sourced here???)
Then, Bash sources ~/.bash_profile
	which sources ~/.bashrc
		which sources /etc/bashrc (but this ends up being a no-op due to a double sourcing check in /etc/bashrc)

Interactive Non-Login Shells

Opening a terminal for example.

Bash sources ~/.bashrc
	which sources /etc/bashrc
		which sources /etc/profile.d/*.sh

Noninteractive Non-Login Shells

Running a script detached from a terminal for example.

Bash sources $BASH_ENV if set.

So Which File Should You Use?

If your operating system provides default files similar to Fedora’s, probably ~/.bashrc. Both it and ~/.bash-profile run when a login shell starts up. Neither are run when a noninteractive non-login shell starts up. All shells will have any environment variables exported in either file. The only difference is for interactive non-login shells.

For that case, ask if the command you’re adding should run each time you open a terminal. If the answer is yes then put it in ~/.bashrc, otherwise put it in ~/.bash_profile. Usually the answer will be yes. Unlike exported variables, aliases and completions aren’t inherited by child processes so they need to be created in each shell. If you want changes to a variable to be automatically picked up by new shells without logging out, then that variable also need to be defined in ~/.bashrc. For example, you may want to change $EDITOR or $TERMINAL after installing or uninstalling a program.

The most common thing I add to ~/.bash_profile is modifications to $PATH. For most other things ~/.bashrc makes more sense.