Bash Initalization Behaviour
A Bash process may be:
|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/profilethen first of
- rc: sources
Note that whether or not the shell is a "login shell" (by the [Bash
manpage definition][Invocation] is not the same as whether the shell
is a "fresh login" in the sense that the profile has ever been run.
The shell process from
ssh host command is not considered a "login
shell" but has never had any of the profile files run.
ssh with no command starts a login shell on the remote,
regardless of whether stdin is a tty or not. Calling ssh with a
bash -c ... which is non-login and non-interactive, but
Bash detects it's "connected to a network connection" (the exact
details of how it decides this are not clear) and sources
.bashrc is not sourced by an interactive login shell. However, the
~/.profile installed by most distros
will, if run under Bash, explicitly source their respective
.bashrc files. If you're not using these, you
almost certainly want to do this too. This will cause
.bashrc to be
executed in some non-interactive situations (e.g.,
echo ls | ssh somehost, since that's a login shell because it was given no remote
command) but you have to handle that anyway as we see below.
Whether or not the profile is sourced,
.bashrc is executed in some
non-interactive situations: in particular, when you
ssh somehost acommand (see table above). The assumption here appears to be that if
you give a command to be executed by the shell you'll want all your
functions and aliases available, and if the command runs a script or
something else that would generate a subprocess, the subprocess would
not inherit the functions/aliases (nor source
.bashrc) and thus not
have its environment polluted by that.
.bashrc should never assume that it's being run in an
interactive environment and do "interactive" things only after
checking to see if the
-i flag is set (see below). In particular,
you should never generate output if you're not interactive as this
breaks non-interactive programs such as
ssh remotehost tar cf - somedir > somedir.tar.
BASH_ENV=~/.bashrc may be tempting but should not be done;
this will pollute the environment of shell scripts and
invocations. Typical problems include:
- Changes made to
$PATHor other environment variables disrupting the environment set up by the parent process.
- Shell functions or aliases shadowing commands executed by a child shell script.
Instead, scripts and invocations that need your functions and/or
aliases should explicitly
source ~/.bashrc and handle having that
entire environment, presumably designed for interactive use, brought
in and potentially overriding the environment set up by the caller.
Test for interactive by checking if
i (this does not
work in old Bourne shell; unknown if it works in POSIX shell):
case $- in *i*) echo interactive;; *) echo or not;; esac
You can also check with
if [ "$PS1" ] ..., but this may not be as
reliable depending on what the user has previously run in his setup.