The Lumber Room

"Consign them to dust and damp by way of preserving them"

Zsh/Bash startup files loading order (.bashrc, .zshrc etc.)

with 50 comments

If you have ever put something in a file like .bashrc and had it not work, or are confused by why there are so many different files — .bashrc, .bash_profile, .bash_login, .profile etc. — and what they do, this is for you.

The issue is that Bash sources from a different file based on what kind of shell it thinks it is in. For an “interactive non-login shell”, it reads .bashrc, but for an “interactive login shell” it reads from the first of .bash_profile, .bash_login and .profile (only). There is no sane reason why this should be so; it’s just historical. Follows in more detail.

For Bash, they work as follows. Read down the appropriate column. Executes A, then B, then C, etc. The B1, B2, B3 means it executes only the first of those files found.

+----------------+-----------+-----------+------+
|                |Interactive|Interactive|Script|
|                |login      |non-login  |      |
+----------------+-----------+-----------+------+
|/etc/profile    |   A       |           |      |
+----------------+-----------+-----------+------+
|/etc/bash.bashrc|           |    A      |      |
+----------------+-----------+-----------+------+
|~/.bashrc       |           |    B      |      |
+----------------+-----------+-----------+------+
|~/.bash_profile |   B1      |           |      |
+----------------+-----------+-----------+------+
|~/.bash_login   |   B2      |           |      |
+----------------+-----------+-----------+------+
|~/.profile      |   B3      |           |      |
+----------------+-----------+-----------+------+
|BASH_ENV        |           |           |  A   |
+----------------+-----------+-----------+------+
|                |           |           |      |
+----------------+-----------+-----------+------+
|                |           |           |      |
+----------------+-----------+-----------+------+
|~/.bash_logout  |    C      |           |      |
+----------------+-----------+-----------+------+

In more detail is this excellent flowchart from http://www.solipsys.co.uk/new/BashInitialisationFiles.html :

Typically, most users will encounter a login shell only if either:
* they logged in from a tty, not through a GUI
* they logged in remotely, such as through ssh.
If the shell was started any other way, such as through GNOME’s gnome-terminal or KDE’s konsole, then it is typically not a login shell — the login shell was what started GNOME or KDE behind your back when you logged in; things started anew are not login shells. New terminals or new screen windows you open are not login shells either. (Starting a new window in OS X’s Terminal.app seems to count as a login shell, though.)

So typically (or sooner or later), what you will encounter are non-login shells. So this case is what you should write your config files for. This means putting most of your stuff in ~/.bashrc, having exactly one of ~/.bash_profile, ~/.bash_login, and ~/.profile, and sourcing ~/.bashrc from it. If you have nothing that you specifically want to happen only for login shells, you can even symlink one of the three to ~/.bashrc. In fact, even if you do, it is probably a good idea to have only file, as follows:

# Bash customisation file

#General configuration starts: stuff that you always want executed

#General configuration ends

if [[ -n $PS1 ]]; then
    : # These are executed only for interactive shells
    echo "interactive"
else
    : # Only for NON-interactive shells
fi

if shopt -q login_shell ; then
    : # These are executed only when it is a login shell
    echo "login"
else
    : # Only when it is NOT a login shell
    echo "nonlogin"
fi

Almost everything should go in the “general configuration” section. There might be some commands (those which produce output, etc.) that you only want executed when the shell is interactive, and not in scripts, which you can put in the first “conditional section”. I don’t see any reason to use the rest. You can drop the “echo” lines, but keep the “:”s — they are commands which do nothing, and are needed if that section is empty.

You then need to have only file, and you can call this ~/.bashrc and do cd && ln -s .bashrc .bash_profile

For zsh: [Note that zsh seems to read ~/.profile as well, if ~/.zshrc is not present.]

+----------------+-----------+-----------+------+
|                |Interactive|Interactive|Script|
|                |login      |non-login  |      |
+----------------+-----------+-----------+------+
|/etc/zshenv     |    A      |    A      |  A   |
+----------------+-----------+-----------+------+
|~/.zshenv       |    B      |    B      |  B   |
+----------------+-----------+-----------+------+
|/etc/zprofile   |    C      |           |      |
+----------------+-----------+-----------+------+
|~/.zprofile     |    D      |           |      |
+----------------+-----------+-----------+------+
|/etc/zshrc      |    E      |    C      |      |
+----------------+-----------+-----------+------+
|~/.zshrc        |    F      |    D      |      |
+----------------+-----------+-----------+------+
|/etc/zlogin     |    G      |           |      |
+----------------+-----------+-----------+------+
|~/.zlogin       |    H      |           |      |
+----------------+-----------+-----------+------+
|                |           |           |      |
+----------------+-----------+-----------+------+
|                |           |           |      |
+----------------+-----------+-----------+------+
|~/.zlogout      |    I      |           |      |
+----------------+-----------+-----------+------+
|/etc/zlogout    |    J      |           |      |
+----------------+-----------+-----------+------+

Moral:
  For bash, put stuff in ~/.bashrc, and make ~/.bash_profile source it.
  For zsh, put stuff in ~/.zshrc, which is always executed.

[Note: This is assuming you care only about interactive shells (shells you can type at). If further you ever use non-interactive shells (like “ssh [host] [command]” which executes [command] on [host] and logs out immediately) and there is something you absolutely absolutely want executed first even for these cases (think carefully: they can interfere in strange ways and you may be able to do without them), then you can put such stuff in ~/.zshenv. For bash, put them in a file and set the value of BASH_ENV to the filename.]

Thanks to this blog post and the manpages for information and ideas.

Written by S

Sun, 2008-03-30 at 19:43:56

Posted in compknow

Tagged with , , ,

50 Responses

Subscribe to comments with RSS.

  1. […] files (~/.bashrc, ~/.bash_profile, ~/.bash_login), restart your terminal, and you are good to go. Here is a great article about how bash configs work. I put tgrep() in my .bashrc file, but also added […]

  2. […] Zsh/Bash startup files loading order (.bashrc, .zshrc etc.) (tags: sysadmin linux zsh) […]

  3. […] for example.) More generally, it’s happening because some command in your ~/.bashrc (or some other file sourced automatically) is expecting the shell to be interactive, when it’s not. The fix is to find out which […]

  4. […] Zsh/Bash startup files loading order (.bashrc, .zshrc etc.) « The Lumber Room […]

  5. Thanks for putting this all together in such a clear and informative way :)
    I’ve referred people to this blog post several times.

    Josh

    Wed, 2011-01-05 at 01:41:13

    • You’re welcome, very glad it helped. That was exactly my purpose in putting this together; I have myself referred to it several times when I was at a new computer. :-)

      S

      Wed, 2011-01-05 at 07:07:07

  6. This is an amazing reference.

    saikobee

    Mon, 2011-01-17 at 14:43:07

  7. Great table; I found this very helpful!

    One minor quibble: you say “For zsh, put stuff in ~/.zshrc, which is always executed,” but .zshrc is not always executed. Do you mean .zshenv? Either way, I think there is a good reason to use both files: .zshenv should never write anything to stdout. If it does, then things like “ssh [myhost] [mycommand]” will return unexpected results.

    However, it may be necessary to set up some environment variables on [myhost] before running [mycommand] — this is what .zshenv is for! Anything else, particularly anything that writes to stdout, should go in .zshrc.

    Drew Frank

    Thu, 2011-06-16 at 18:51:00

    • [Edit: I’ve updated it, thanks.]

      Thanks. I guess when I wrote that, I only cared about interactive shells, and only wanted not to have to bother about login versus non-login shells. If you notice, the instructions for Bash similarly only cover interactive shells. :-) Actually, Bash doesn’t even have the equivalent of ~/.zshenv which is executed for non-interactive shells, so IMO it’s not crucial.
      I’m not convinced there is really anything I absolutely want done on remote systems when running things like “ssh [myhost] [mycommand]”, but yes, if someone wants it then it’s a good idea to mention it in the post as well.

      S

      Fri, 2011-06-17 at 00:49:30

  8. Awesome article, I’ve been looking for this. People are lazy to read manuals etc… It can’t be more simple. Thanks.

    Ahmet Yasin Uslu

    Fri, 2011-08-12 at 05:48:58

  9. it helped me lot. thanks

    Anonymous

    Mon, 2011-11-07 at 16:37:12

  10. thanks a lot. the post is informative.

  11. There is a wonderful diagram of the Bash initialization process here: http://www.solipsys.co.uk/new/BashInitialisationFiles.html?HN0811

    Jonas Gorauskas

    Mon, 2012-09-03 at 08:01:48

    • Really cool. Thanks I’ve gone ahead and added it to the article.

      S

      Mon, 2012-09-03 at 10:44:19

  12. Nice start, but you still need to account for /etc/bashrc, /etc/bashrc.local, /etc/bash.bashrc.local, /etc/rc.common, /etc/rc.conf, /etc/rc.local, and more, depending on system. :-) E.g., for bash on Mac OS X 10.8, /etc/rc.common loads first, then /etc/profile then /etc/bashrc (there are no bash.*), etc.

    Stanton McCandlish

    Tue, 2013-10-22 at 13:54:33

  13. […] from testing for interative terminal in .bashrc, bash_profile vs bashrc and Zsh/Bash startup files loading order (.bashrc, .zshrc etc.) […]

  14. […] make this addition persistent you can also add that to your .profile, .bash_profile or .zprofile depending on the shell and setup you […]

  15. […] make this addition persistent you can also add that to your .profile, .bash_profile or .zprofile depending on the shell and setup you […]

  16. […] In order, your machine will load/execute the following files when ZSH starts: […]

  17. […] After reading this post I've tweaked the setup to put everything in .bashrc and then source that from .bash_profile (and […]

  18. […] Zsh/Bash startup files loading order (.bashrc, .zshrc etc.) […]

  19. […] Information on how terminals read settings at https://shreevatsa.wordpress.com/2008/03/30/zshbash-startup-files-loading-order-bashrc-zshrc-etc/ […]

  20. This is really great! Thanks a lot for writing this up.

    이상현 (@sangdolha)

    Sun, 2017-02-19 at 08:20:33

  21. Loved it :D

    Nadim Tuhin

    Wed, 2017-05-10 at 15:31:18

  22. coool graph…

    Anonymous

    Thu, 2019-05-09 at 20:29:44

  23. […] Zsh/Bash startup files loading order (.bashrc, .zshrc etc.) […]

  24. […] configuration files it checks, and some of those the user may have chained together. So far, even the best resource on the matter I’ve found doesn’t tell the whole […]

  25. […] Zsh/Bash startup files loading order […]

  26. […] out, I’ll always be to afraid to find out if zsh is worth using. Fortunately, I have a handy guide I can use to get a zsh initialization […]

  27. […] 이 블로그 에 따르면 zsh시작시 (를 포함하여 .profile) 많은 파일을 읽습니다 . […]

  28. […] ShreevatsaR 의이 훌륭한 블로그 게시물을 살펴보십시오 . 다음은 추출 내용이지만 블로그 게시물로 이동하면 “로그인 쉘”과 같은 용어에 대한 설명, 순서도 및 Zsh와 유사한 표가 포함됩니다. […]

  29. data analytics training institute offers data analytics courses in big data, data science, AI & ML in Bangalore. Learnbay list of top 5 Data Science Institutes in Bangalore offers proper guidance.

    Avail The Data Science Courses in Bangalore and Kick Start Your Career as a Successful Data Scientist in Bangalore within 4-5 months

    skillslashlearning

    Mon, 2021-10-04 at 05:07:09

  30. […] shown on this site, .bashrc loads before […]

  31. […] should be set in ~/.zshenv. You can find additional information in the zshall manpage and on this site. ~/.zshprofile will (usually) also not be parsed by any other tools. So any environment variables […]

  32. […] web site has a lot of information about […]

  33. […] 第一张图来自这篇 文章 ,bash的每种模式会读取其所在列的内容,首先执行A,然后是B,C。而B1,B2和B3表示只会执行第一个存在的文件: […]

  34. […] web site has a lot of information about […]

  35. […] Zsh/Bash startup files loading order (.bashrc, .zshrc etc.) […]


Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.