For many years I was a bit hazy on the difference between .bashrc and
.bash_profile (or .profile). I knew that .bashrc was sourced by Bash when
it ran an interactive shell, and I knew that .bash_profile was sourced by Bash
when it ran a login shell, but I confess I didn't understand exactly how to use
this distinction effectively.
When .bash_profile And .bashrc Are Run
Assuming you have your shell set to /bin/bash, there are generally three times
when Bash will source your .bash_profile file:
- if you log into a machine over SSH
 - if you log in via a Linux virtual console
 - it will be sourced by GDM/GNOME if you have a graphical login session started in the usual way
 
A key thing to understand here is that when the .bash_profile file is sourced
in this way, it will affect all future processes created from that
SSH/X11/console session. Therefore it should only contain the most important
configuration.
The .bashrc file will be run whenever a new terminal window is opened. It will
not automatically be sourced if you log in via SSH or a virtual console. In
a GNOME session (or whatever window manager you prefer) the .bashrc file will
be executed every time you open a new terminal "window".
Combining The Two
Your .bash_profile file should set up everything that needs to be run just
once and will be needed by any later programs. There are at least two important
cases:
- you should set up your SSH agent here
 - anything important in your 
PATHshould be set up here, so that theexec()family of system calls will be able to find executables 
If you're using GNOME it will actually automatically launch a
gnome-keyring-daemon process for you that acts as an SSH agent. I strongly
recommend against using it. I wrote
an article about this previously. In the previous article
I advocated using Envoy, but now I prefer to just use a regular ssh-agent
process which is simpler and more effective now that I figured out how to nuke
all of the gnome-keyring stuff.
In my .bash_profile I have the following code:
eval $(ssh-agent) &>/dev/null
ssh-add &>/dev/null
export SSH_AUTH_SOCK
# source .bashrc only if this is a VT or SSH connection
if [ $(env | grep -c SSH_CONNECTION) -ne 0 ] || [ $TERM = "linux" ]; then
    source ~/.bashrc
fi
This creates an ssh-agent process in the usual way and adds my key to it. It
also checks if I'm connected from an SSH connection, or if I'm logged in via a
virtual console (uncommon, but happens from time to time). In either of those
cases it will source .bashrc.
In my .bashrc file I have code related to setting up a decent prompt (i.e
PS1 and PS2) and some useful interactive aliases and whatnot. The whole
thing is pretty small. As I write this, my .bash_profile is 33 lines long and
my .bashrc is 116 lines long (most of which is weird stuff I need for obsure
reasons at work). Aliases and prompt configuration should only be defined in
.bashrc, not in .bash_profile.
I strongly recommend against unconditionally sourcing .bashrc from your
.bash_profile or .profile. You should only source it if you're actually in
an interactive session, and the above is a good way to test that.
Update: It's been
pointed out to me
that instead of the byzantine check that I had above for checking for
SSH_CONNECTION and TERM, one can simply do:
test -t 0 && source ~/.bashrc
This is kind of a nice approach because besides being simpler, it will work in a wider variety of environments (e.g. OS X).
Nuking gnome-keyring-daemon
It's really easy to prevent the gnome-keyring-daemon from running:
sudo ln -sf /dev/null /etc/xdg/autostart/gnome-keyring-ssh.desktop
Do this once and you'll never have to worry about it interfering with your
ssh-agent process ever again.
In addition to this, in my .bashrc I have:
unset SSH_ASKPASS
In the unlikely situation where you don't have any SSH keys loaded this will prevent the annoying GNOME graphical popup from asking you for an SSH password.