The confusing Bash configuration files

This blog is mostly a reminder for my future self, because I always end up forgetting this.

Bash has a bunch of configuration files it parsers through when you fire it up.

Bash reads them in this order (on Fedora, and I suppose RHEL and derivatives too) if invoked as an interactive login shell (i.e. when you log into the system on the console, or through SSH):

  • /etc/profile (if it exists)

  • ~/.bash_profile (if it exists)

  • ~/.bash_login (if it exists, and ~/.bash_profile does not exist)

  • ~/.profile (if it exists, and if the above two files do not)

When exiting, the interactive login shell executes:

  • ~/.bash_logout (if it exists)

  • /etc/bash.bash_logout (if it exists)

For an interactive non-login shell (that’s when you start gnome-terminal or tilix in X or Wayland), Bash just executes ~/.bashrc, if it exists. (So, no, /etc/bashrc is not invoked by Bash itself, but usually through ~/.bashrc, which by default sources /etc/bashrc.)

Because this is odd, the default ~/.bash_profile actually sources ~/.bashrc.

So for an interactive login shell, this happens (assuming the default config files from /etc/skel on Fedora 28):

  1. /etc/profile is read,

  2. whatever is in /etc/profile.d is included

  3. /etc/bashrc is included, and the ${BASHRCSOURCED} variable is set to Y

  4. ~/.bash_profile is read

  5. ~/.bashrc is sourced through ~/.bash_profile

  6. /etc/bashrc is sourced, again, this time through ~/.bashrc, but it’s not actually parsed again, because ${BASHRCSOURCED} was already set to Y

  7. neither ~/.bash_login, nor ~/.profile are sourced, because ~/.bash_profile exists

  8. You get your shell

Finally, when Bash is invoked as the interpreter for a shell script, it will read ${BASH_ENV}, and it will read and execute the filename it finds in there. For Fedora 28, that’s /usr/share/Modules/init/bash, owned by the environment-modules package.

Mind that this only happens if the shell script starts with the proper Bash shebang: #!/bin/bash or #!/usr/bin/bash, not with #!/bin/sh. Starting your shell script with #!/bin/sh will yield completely different results, as that will make Bash run in compatibility mode for old(er) shells.

Maxim Burgerhout

Maxim Burgerhout

Solution architect at Red Hat for the platform and cloud portfolio; likes Python, likes Ruby, internally conflicted about that; maintainer of @RedHatSatellite

Read More
comments powered by Disqus
The confusing Bash configuration files
Share this