1

I was confused in what order my shells source which files. When researching this for myself, I came across several sources online and even read some parts of the manuals for both shells. But still, information seemed contradicting and wrong at times.

I understand that there can't be a perfect overview of all the shells, but is there some overview somewhere which shows what files are sourced by Bash and Zsh, and in what order/circumstances? For example, how does the sourcing differ when the shell is non-interactive?

3

1 Answer 1

2

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

Bash startup files flow-chart

Zsh

Zsh startup files flow-chart

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.

4
  • At least the zsh diagram is wrong. A zsh processes, irrespective of its type, first of tall /etc/zshenv. This file isn't even mentioned in your diagram. The diagram also does not depict the dependency on the ZDOTDIR environment variable. Also, ~/.zshenv is source earlier than ~/.zshrc. Unless I misunderstand your diagram completely, this is also not visible in your picture. Commented May 2 at 13:56
  • @user1934428 thanks for your feedback! /etc/zshenv indeed is not mentioned in the diagram, but it is equivilent to /etc/zsh/zshenv in my experience. And yes, I believe you are misreading my graph, but that's feedback too. And, indeed, ZDOTDIR should also be mentioned.
    – Silas
    Commented May 2 at 18:28
  • The zsh manpage does not mention /etc/zsh/zshenv, and on my platform, there isn't even a /etc/zsh directory. Perhaps your system has a symlink from /etc/zshenv into /etc/zsh/zshenv? Commented May 3 at 5:55
  • @user1934428 that's sort of correct, Manjaro stores all Zsh files in /etc/zsh by default. When moving or copying them to /etc, everything works the same.
    – Silas
    Commented May 24 at 14:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .