With this overview, I hope to end any confusion and introduce an easy overview of which files are sourced under what circumstances, for Bash and Zsh. The diagrams below have been tested on an archlinux vanilla install on a VM.
Startup files sourcing orders
Bash
Zsh
The diagrams above displays in what order the scripts are sourced, depending on whether the shell is login, non-login, interactive or non-interactive.
To follow the sourcing order of one combination, start at the most-left node and 'choose' your combination. You will end up with only one color passing both choices of login/interactive: that's the color to follow!
Notes on the diagram
Files in /etc/zsh/
, if present in /etc/
, function exactly the same. Both paths are equal, and are sourced. Furthermore, this graph assumes that ZDOTDIR
is unset. If set, all files sourced in ~
are instead sourced from ZDOTDIR
.
Notes
Types of startup files (overview)
A diagram is great, but words have their nuance as well, so here goes.
There are X types of startup files (files sourced when the shell starts): 'env', 'profile', 'rc', 'login' and 'logout', which are sourced in this presedence.
Depending on your shell, the files of these types have a slightly different naming.
All those types, come both in system-wide and user scoped variants, placed respectively in /etc
and $HOME
. Those in $HOME
work only for the belonging user, but those system-wide are sourced by everyone - even root - and is maintained by the system admin.
'env' files are just for defining global variables, nothing more! Profile files commonly define more specific variables and functions. 'rc files are intended interactive shells, enriching the shell with things like the prompt and other tools to make interaction a brease. 'login' and 'logout' are for, well, logging in and logging out, and there just so you have extra options on when certain things are sourced.
Intended purposes of startup files
Not all original intentions for a startup file may be obvious enough. Thus, here is extra explenation on some of the files:
/etc/profile
: typically used to source /etc/bash.bashrc
.
*zlogin
: has the exact same purpose as *zprofile
, but is intended for logic who depends on the shell being fully configured by other files. Its only difference is indeed that it is sourced after *zshrc
, not before. Commonly used to run startx
or other display managers.
/etc/zsh/zprofile
: must source /etc/profile
through emulate sh -c
, or some common scripts like make will break.
/etc/bash.bashrc
: typically loads bash_functions.
~/.bash_profile
: typically used to source ~/.bashrc
since ~/.bashrc
is not sourced when in a login shell - while there are scenarios you actively use a login-shell.
Other notable remarks
- Some distros (at least Manjaro I believe) also have Zsh files in
/etc/
, instead of /etc/zsh/
. Both are the same, and on Manjaro only one of both will be sourced.
- Some distros, like ubuntu, have additional startup files available to utilise.
- Logout scripts in bash are not run in an non-interactive shell, unless
bye
, logout
, or exit
(or other similar commands) is executed.
- Please realise that
*zshenv
is sourced even by make
! (Hence you keep these files as simple as possible.) Commands in *zshenv
files are thus reccommended to always be surrounded with the follownig code:
if [[ ! -o norcs ]]; then
echo 'your command'
fi
Main difference Zsh and Bash
Bash seems to seperate startup files for login shells from interactive shells. If the interactive login-shell runs a display manager, you generally do not need configs an interactive shell would need, since you won't directly interact with it anyway. However, in other scenarios (for example, when SSH'ing), you would like those interactive shell configs to be sourced.
Zsh does not seperate both: interactive scripts are run when interactive, and login shells are run when login-shell; simple.
Also, notice how ~/.profile
is not sourced by zsh, and is instead replaced with it's own ~/.zprofile
.
What is my sourcing order?
I tested the full sourcing order, by prepending the following line in every startup file, where FILE_NAME
is the startup file's name:
export startup_trace="$startup_trace\nFILE_NAME"
For *logout
startup files, I instead echoed the filename since you cannot print the updated trace after exiting.
To test a trace for an non-interactive Zsh login-shell, for example, run the following command:
su $SOME_USER -ls /bin/zsh -c 'setopt; echo -e $startup_trace; exit'
This will print, in order, all the files that were sourced.
Notice how exit
also tests the *logout
startup files.
/etc/bash.bash_logout
.