Bash Invocation
Historically, Bash invocation has confused many users, both experts and newbies. Bash forums are filled with questions such as:
-
Why weren’t my commands executed?
-
Which file to source at Bash startup?
-
What’s the difference between
.bashrc
,.bash_profile
,.profile
,.bash_login
…
So we are going to clarify how Bash is invoked in this text.
Login/Non-Login Shell
The first question people ask is often: What is a login shell?
Possible answers I’ve seen:
A login shell is one whose first character of argument zero is a
-
, or one started with the--login
option. (Origin)A login shell is the first process that executes under your user ID when you log in for an interactive session. (Origin)
…a login shell is one that is spawned by the login process. (Origin)
Putting them together, a login shell is used for user login, and is identified
by, either a -
as first character of argument zero, or a --login
option.
The login shell of a user is stored in /etc/passwd
. And you can use getent
passwd <username>
to see it. The login process will spawn the login shell on
a successful login.
Another way to start a login shell is to invoke it with a --login
option:
bash --login
Another way to start a login shell is to set the first character of argument
zero to a -
when invoke the shell:
exec -a -bash bash
To check whether a shell is a login shell, use:
shopt -q login_shell
Interactive/Non-Interactive Shell
The definition in Bash Manual is:
An interactive shell is one started without non-option arguments, unless
-s
is specified, without specifying the-c
option, and whose input and error output are both connected to terminals (as determined byisatty
(3)), or one started with the-i
option.
The statement is more clearly viewed as:
-
(
-
(without non-option arguments, unless
-s
is specified) -
and
-
(without specifying the
-c
option) -
and
-
(whose input and error output are both connected to terminals (as determined by
isatty
(3)))
-
-
)
-
or
-
(
- one started with the
-i
option.
- one started with the
-
)
To check whether a shell is an interactive shell, use:
[[ $- == *i* ]]
Login and/or Interactive
Now that login-ness and interactive-ness classify Bash shells in different dimensions, users may wonder whether a shell can be either or both.
The answer is, a shell can be none, either or both, because these two properties are orthogonal. Here are some typical use cases exemplifying these different properties:
-
non-login, non-interactive:
When you run a shell script in a terminal window with
bash myscript.sh
, the started shell is a non-login, non-interactive shell. -
non-login, interactive:
When you start another shell without any arguments with
bash
, the started shell is a non-login, interactive shell. -
login, non-interactive:
This use case is very rare. One way to start this kind of shell is:
echo 'shopt login_shell; echo $-' | ssh {server}
-
login, interactive:
When you login from terminal after entering username and password, the started shell is a login, interactive shell.
Startup Scripts
Bash sources different scripts on start, depending on how it is invoked. Here’s a standard list of them:
~/.bash_login
~/.bash_profile
~/.bashrc
~/.profile
/etc/profile
Basic sourcing rules are:
-
When Bash is invoked as a login shell, it sources
/etc/profile
then the first one in[ ~/.bash_profile, ~/.bash_login, ~/.profile ]
. -
When Bash is invoked as a non-login, interactive shell, it sources
~/.bashrc
. -
When Bash has its standard input connected to a network connection (as when executed by a remote shell daemon such as
sshd
), it sources~/.bashrc
.
Note that these rules come from real tests, whose results do not exactly match
Bash Manual. Specifically, Bash Manual does not mention the case where a login
shell is one whose first character of argument zero is a -
. Under our tests,
this case makes no difference than other login cases.
Conclusion
To summarize:
-
Interactive shells source either profile or rc depending on whether it’s login/non-login.
-
Non-interactive shells source profile when invoked with
--login
(or whose first character of argument zero is a-
). -
Bash shells with network-connected stdin source rc.