chepner's answer covers the overall principles. There are a few other subtleties that you want to take note of.
First, login shells do not source .bashrc
even if they are interactive. Thus, you probably want a .bash_profile
that contains code like the following:
interactive() { [[ $- = *i* ]]; }
interactive && . $HOME/.bashrc || echo 1>&2 "ERROR: .bashrc failed with retval $?"
This won't make much difference on a console login into a graphical environment, but will make quite a difference on a text console or ssh login.
You don't necessarily need to do the interactive test; I actually source .bashrc
even for non-interactive shells (though this is arguably not a good idea in some circumstances).
Note that if you use non-Bash shells as well, you'll also need a .profile
with whatever environment variables etc. you want for those. Bash will ignore your .profile
when you have a .bash_profile
, but of course the latter can source the former.
Not every fresh login (i.e., a shell created not by your user id but by a root process that has authenticated you) is considered a "login shell." In particular, giving a command to an ssh invocation (ssh somehost.example.com 'echo $-'
) will not be a "login shell" and .bash_profile
/.bash_login
/.profile
will not be sourced. Here's a table showing what's considered a "login" or interactive shell and what's executed for various invocations
State |
Invocation |
Login (L) |
argv[0][0] == '-' , --login |
Interactive (I) |
-i , stdin is tty |
Remote (R) |
stdin is "network connection" (see below) |
- '•' = set; blank = not set; '-' = not checked or don't care.
- inh: Inherits environment from a parent (other than init);
i.e., it's not a "fresh login" and the parent may expect that
the environment be kept intact.
- p: sources
/etc/profile
then first of ~/.bash_profile
, ~/.bash_login
, ~/.profile
- rc: sources
/etc/bash.bashrc
then ~/.bashrc
L |
I |
R |
|
inh |
p |
rc |
|
Example |
• |
• |
- |
|
|
• |
|
|
ssh host.com (sshd sets argv[0]="-bash") |
• |
|
- |
|
|
• |
|
|
ssh host.com </dev/null (sshd sets argv[0]="-bash") |
|
• |
|
|
• |
|
• |
|
bash -i , bash on tty |
|
|
|
|
• |
|
|
|
bash hello.sh , bash -c echo foo , |
|
|
• |
|
|
|
• |
|
ssh host.com 'echo $-' (ssh runs bash -c 'echo $- ) |
The table comes from this document; there's some further information there that might also be useful. (Anybody who feels something there should be in this answer should feel free to edit this and copy it in.)