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 argument 0, 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.

It’s also possible to manually start a login shell by invoking it with a --login option. You can also link it to - and invoke it, and this is also a login shell even without the --login option.

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 by isatty(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.
  • )

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 because if a login program is non-interactive, then usually we don’t call it a shell…

    So the example here is artifical: bash -l myscript.sh starts a login, non-interactive shell.

  • 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

There are several sourcing rules, of which the most basic ones are as follows:

  • If Bash is invoked as an interactive login shell, or as a non-interactive shell with --login option, it sources /etc/profile and the first one in [~/.bash_profile, ~/.bash_login, ~/.profile].

  • If Bash is invoked as a non-login, interactive shell, it sources ~/.bashrc.

The idea is that, Bash sources startup scripts only when being used interactively (or forced with --login). Depending on login/non-login property, either a profile or a rc file is sourced.

However, please note that stating login shells alway source profile is wrong. A counter example is, when executing a script with argument 0 -, the shell is a login shell, but no profile will be sourced. The shell must be interactive for the statement to hold.

An additional case is when Bash has its standard input connected to a network connection, as when executed by a remote shell daemon (for example, sshd). If so then Bash sources ~/.bashrc.

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.

  • Bash shells with network-connected stdin source rc.