05 09 | 2011

Startup scripts of Bash and Zsh

Written by Tanguy

Classified in : Homepage, Debian, Command line, To remember

Both Bash and Zsh use several startup scripts: profile, bashrc, zlogin, zshrc, etc.

The existence of several startup scripts exists to allow you to apply specific actions for interactive or login shells. For instance, you may want to set up a fancy colour prompt or to enable a powerful completion system for interactive shells only, as it would be pointless to apply it to non-interactive shells (that is, for shell scripts). Or you may want to display a joke and the weather forecast at login, but not each time you spawn a shell by other means.


Both Bash and Zsh first execute a system-wide file, then the corresponding user-specific one. For instance, /etc/profile then ~/.profile. For simplicity I shall only mention the files' base names.


At startup, depending on the case:

  • run as a login shell (or with the option --login), it executes profile (or bash_profile instead if it exists (only user-specific version));
  • run as an interactive, non-login shell, it executes bashrc (the system-wide version is called bash.bashrc).

At exit, it executes ~/.bash_logout (the system-wide version is called bash.bash_logout).

Note the funny (read: insane) non-login condition for executing bashrc: it is often worked around by having the profile execute bashrc anyway.


Zsh always executes zshenv. Then, depending on the case:

  • run as a login shell, it executes zprofile;
  • run as an interactive, it executes zshrc;
  • run as a login shell, it executes zlogin.

At the end of a login session, it executes zlogout, but in reverse order, the user-specific file first, then the system-wide one, constituting a chiasmus with the zlogin files.


yes no
no profile-
yes no
interactiveyeszshenv zprofile zshrc zloginzshenv zshrc
no zshenv zprofile zlogin zshenv

I personally find the Zsh process much saner. To be honest I should rather say that I find Bash's behaviour insane, with an absurd process (bashrc for interactive, non-login shells…) that needs to be worked around, and an inconsistent naming and search convention (~/.bashrc vs. /etc/bash.bashrc, no system-wide version of bash_logout).


monday 05 september 2011 à 14:09 Tanguy said : #1

You may wonder what is a non-interactive login shell. Answer: a shell started to run a single script, with the option --login.

Yes, this is crazy, but it is possible, so with the point of view of the shell author: there will be crazy users to do that, so it must be covered.

wednesday 07 september 2011 à 17:16 Alex said : #2

Actually /etc/bash.bash_logout is the system-wide version of bash_logout ;-) But I totally agree with your name convention complain

thursday 19 april 2012 à 16:52 Elmar Heeb said : #3

I just tested the non-interactive login shell combinationfor bash using the she-bang line "#!/bin/bash -l" and it turns out to be crazier still. /etc/profile is sourced while $HOME/.profile is not.

To reproduce this just put some echo commands in /etc/profile and $HOME/.profile respectively identifying each case.

I consider this a minor bug in bash. Non-interactive shells should not source any config files as they would render shell scripts dependent on settings meant for a specific environment. Without that bug the rule for bash is simple: profile is for login shells, bashrc for non-login shells and scripts get nothing.

Write a comment

What is the last letter of the word ifpd? :