When working with Linux, Unix, and Mac OS X, I always forget which bash config file to edit when I want to set my PATH
and other environmental variables for my shell. Should you edit .bash_profile
or .bashrc
in your home directory?
You can put configurations in either file, and you can create either if it doesn’t exist. But why two different files? What is the difference?
According to the bash man page, .bash_profile
is executed for login shells, while .bashrc
is executed for interactive non-login shells.
What is a login or non-login shell?
When you login (type username and password) via console, either sitting at the machine, or remotely via ssh: .bash_profile
is executed to configure your shell before the initial command prompt.
But, if you’ve already logged into your machine and open a new terminal window (xterm) inside Gnome or KDE, then .bashrc
is executed before the window command prompt. .bashrc
is also run when you start a new bash instance by typing /bin/bash
in a terminal.
Why two different files?
Say, you’d like to print some lengthy diagnostic information about your machine each time you login (load average, memory usage, current users, etc). You only want to see it on login, so you only want to place this in your .bash_profile
. If you put it in your .bashrc
, you’d see it every time you open a new terminal window.
Mac OS X — an exception
An exception to the terminal window guidelines is Mac OS X’s Terminal.app, which runs a login shell by default for each new terminal window, calling .bash_profile
instead of .bashrc
. Other GUI terminal emulators may do the same, but most tend not to.
Recommendation
Most of the time you don’t want to maintain two separate config files for login and non-login shells — when you set a PATH
, you want it to apply to both. You can fix this by sourcing .bashrc
from your .bash_profile
file, then putting PATH
and common settings in .bashrc
.
To do this, add the following lines to
.bash_profile
:
if [ -f ~/.bashrc ]; then source ~/.bashrc fi
Now when you login to your machine from a console .bashrc
will be called.
Comments
Thanks for enlightening, I was mystified on this front ..
Thank you - that really helped me
This may give undesirable results should you run a remote (non-interactive) shell-calling program (e.g.: scp). It’s probably wisest to use these .rc files as they were designed to be used. Alas, I’m not exactly sure how they were designed to be used. :-P I use tcsh, so I copied all of my old .tcshrc file into .tcsh_profile and combined the calls to .cshrc and .alias into .tcsh_profile while I was at it. Now when I login I don’t get any of my settings, but at least scp works again. Ah "progress"!
I’ve been calling .bashrc from .bash_profile on my remote machine for a while and have never had a problem with scp, but I suppose it depends on the content of those files.
Thanks a lot! This issue has been gnawing me for months!
Wouldn’t this cause problem if you run one script from the other in both of them? For example, if you have those 3 lines to include .bashrc in .bash_profile, then it starts executing .bashrc and then reaches those 3 lines in .bashrc and starts to execute .bash_profile. Doesn’t this result in some sort of recursive stack overflow?
I absolutely despise coloring ls output. ls -F is the obviously correct solution.
It’s OK to call .bashrc from .bash_profile as long as you’re careful what commands you put in .bashrc. However you should never call .bash_profile from .bashrc. If you really want to execute .bash_profile, just start bash with a ’-l’ (or a ’--login’ if you prefer) option.
I absolutely despise coloring ls output. ls -F is the obviously correct solution.
Well, that’s a personal preference. But ls -F is horrible IMO: those tacked on characters make files look like they have wonky names, to the extent that novice users even try to type them in as part of the name (which has caused me tech support hassle in the past). Coloring produces no such confusion- you don’t get people confused because they can’t type a green filename or purple filename, wanting to because "that’s how it looks in the listing"...
Certain terminal emulators can be set to execute login shells rather than regular shells. And this has security benefits, IIRC, with regards to things that get logged to the system log (mostly to do with su/sudo, I’d have to look it up).
.bashrc is also run whenever you run a script written in bash. So if you want to have /usr/games/fortune spit you out a funny bit of wisdom, you should make it run in .bash_profile, NOT .bashrc, unless you want to see a fortune every time an sh process gets directly or indirectly executed by a script (I did this once, and man, compiling packages from source got a little more interesting at least).
You should use ~/.profile for setting environment variables or executing login scripts. That way if you decide to switch to another shell (or if bash is for some reason unavailable - due to a disk failure for example) you won’t need to move those scripts out of ~/.bash_profile - they’ll be appropriately executed from ~/.profile.
Any bash-specific settings should be set in ~/.bashrc, so that they will be set even if you execute bash from another shell or xterm (ie if bash is not your login shell for that session).
All of this is clearly stated in the bash man page (ie ’man bash’ at the command line), as well as the user guide.
It’s OK to call .bashrc from .bash_profile as long as you’re careful what commands you put in .bashrc.
It is not just OK - it is standard/typical behaviour as stated by the user guide.
However you should never call .bash_profile from .bashrc.
Especially if you’re already calling .bashrc from .bash_profile. ;-)
This finally explained why I never saw my ~/.bashrc settings when I would login interactively.
I tested the if/then contruct in my ~/.bash_profile and, sure enough, I get my fancy PS1 settings and all my aliases.
Why not just hardlink .bashrc to .bash_profile and have one file to edit?
I typically check .bash_profile for anything useful. If there’s anything in there I want to keep, I move the contents to .bashrc. I then symlink .bash_profile to .bashrc to keep things simple.
I also used to use the `source .bashrc` method you mentioned, but in the end I found it simpler to have only one file to maintain.