What's the difference between .bashrc, .bash_profile, and .environment?
ShellEnvironmentBashShell Problem Overview
I've used a number of different *nix-based systems of the years, and it seems like every flavor of Bash I use has a different algorithm for deciding which startup scripts to run. For the purposes of tasks like setting up environment variables and aliases and printing startup messages (e.g. MOTDs), which startup script is the appropriate place to do these?
What's the difference between putting things in .bashrc
, .bash_profile
, and .environment
? I've also seen other files such as .login
, .bash_login
, and .profile
; are these ever relevant? What are the differences in which ones get run when logging in physically, logging in remotely via ssh, and opening a new terminal window? Are there any significant differences across platforms (including Mac OS X (and its Terminal.app) and Cygwin Bash)?
Shell Solutions
Solution 1 - Shell
The main difference with shell config files is that some are only read by "login" shells (eg. when you login from another host, or login at the text console of a local unix machine). these are the ones called, say, .login
or .profile
or .zlogin
(depending on which shell you're using).
Then you have config files that are read by "interactive" shells (as in, ones connected to a terminal (or pseudo-terminal in the case of, say, a terminal emulator running under a windowing system). these are the ones with names like .bashrc
, .tcshrc
, .zshrc
, etc.
bash
complicates this in that .bashrc
is only read by a shell that's both interactive and non-login, so you'll find most people end up telling their .bash_profile
to also read .bashrc
with something like
[[ -r ~/.bashrc ]] && . ~/.bashrc
Other shells behave differently - eg with zsh
, .zshrc
is always read for an interactive shell, whether it's a login one or not.
The manual page for bash explains the circumstances under which each file is read. Yes, behaviour is generally consistent between machines.
.profile
is simply the login script filename originally used by /bin/sh
. bash
, being generally backwards-compatible with /bin/sh
, will read .profile
if one exists.
Solution 2 - Shell
That's simple. It's explained in man bash
:
/bin/bash
The bash executable
/etc/profile
The systemwide initialization file, executed for login shells
~/.bash_profile
The personal initialization file, executed for login shells
~/.bashrc
The individual per-interactive-shell startup file
~/.bash_logout
The individual login shell cleanup file, executed when a login shell exits
~/.inputrc
Individual readline initialization file
Login shells are the ones that are read one you login (so, they are not executed when merely starting up xterm, for example). There are other ways to login. For example using an X display manager. Those have other ways to read and export environment variables at login time.
Also read the INVOCATION
chapter in the manual. It says "The following paragraphs describe how bash executes its startup files.", i think that's a spot-on :) It explains what an "interactive" shell is too.
Bash does not know about .environment
. I suspect that's a file of your distribution, to set environment variables independent of the shell that you drive.
Solution 3 - Shell
Classically, ~/.profile
is used by Bourne Shell, and is probably supported by Bash as a legacy measure. Again, ~/.login
and ~/.cshrc
were used by C Shell - I'm not sure that Bash uses them at all.
The ~/.bash_profile
would be used once, at login. The ~/.bashrc
script is read every time a shell is started. This is analogous to /.cshrc
for C Shell.
One consequence is that stuff in ~/.bashrc
should be as lightweight (minimal) as possible to reduce the overhead when starting a non-login shell.
I believe the ~/.environment
file is a compatibility file for Korn Shell.
Solution 4 - Shell
I found information about .bashrc and .bash_profile here to sum it up:
> .bash_profile is executed when you > login. Stuff you put in there might be > your PATH and other important > environment variables. > > .bashrc is used for non login shells. > I'm not sure what that means. I know > that RedHat > executes it everytime you start > another shell (su to this user or > simply calling bash again) You might > want to put aliases in there but again > I am not sure what that means. I > simply ignore it myself. > > .profile is the equivalent of > .bash_profile for the root. I think > the name is changed to let other > shells (csh, sh, tcsh) use it as well. > (you don't need one as a user) > > There is also .bash_logout wich > executes at, yeah good guess...logout. > You might want to stop deamons or even > make a little housekeeping . You can > also add "clear" there if you want to > clear the screen when you log out.
Also there is a complete follow up on each of the configurations files here
These are probably even distro.-dependant, not all distros choose to have each configuraton with them and some have even more. But when they have the same name, they usualy include the same content.
Solution 5 - Shell
According to Josh Staiger, Mac OS X's Terminal.app actually runs a login shell rather than a non-login shell by default for each new terminal window, calling .bash_profile instead of .bashrc.
He recommends:
> 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.
Solution 6 - Shell
A good place to look at is the man page of bash. Here's an online version. Look for "INVOCATION" section.
Solution 7 - Shell
I have used Debian-family distros which appear to execute .profile
, but not .bash_profile
,
whereas RHEL derivatives execute .bash_profile
before .profile
.
It seems to be a mess when you have to set up environment variables to work in any Linux OS.