This is addressed nicely in the book Unix Power Tools (Oreilly):
When you first log in to a Unix system from a terminal, the system normally starts a login shell. A login shell is typcally the top-level shell in the “tree” of processes that starts with the
initprocess. Many characteristics of processes are passed from parent to child process down this “tree” — especially environment variables, such as the search path. The changes you make in a login shell will affect all the other processes that the top-level shell starts — including any subshells.
So, a login shell is where you do general setup that’s done only the first time you log in — initialize your terminal, set environment variables, and so on. […]
So you could think about a login shell as a shell that is started at startup by the
init process (or
systemd nowadays). Or as a shell that logs you into the system by your providing a username and a password. A nonlogin shell, by contrast, is a shell that is invoked without logging anybody in.
Is My Current Shell a Login Shell?
There are two ways to check if your current shell is a login shell: First, you can check the output of
echo $0: if it starts with a dash (like
-bash), it’s a login shell. Be aware, however, that you can start a login shell with
bash --login, and
echo $0 will output just
bash without the leading dash, so this is not a surefire way of find out if you are running a login shell.
Secondly, the Unix StackOverflow offers this way of finding out:
$ shopt -q login_shell && echo login || echo nonlogin
-q supresses the output of the
The Difference Between Login and Nonlogin That Actually Matters
Practically speaking, the difference between a login shell and a nonlogin shell is in the configuration files that Bash reads when it starts up. In particular, according to
[…] it first reads and executes commands from the file
/etc/profile, if that file exists. After reading that file, it looks for
~/.profile, in that order, and reads and executes commands from the first one that exists and is readable.
You can observe this behavior by putting
echo commands in
~/.profile. Upon invoking
bash --login you should see:
echo from /etc/profile echo from ~/.bash_profile $
If the shell is a nonlogin shell, Bash reads and executes commands from
~/.bashrc. Since we are starting a nonlogin shell from within a login shell, it will inherit the environment. Sometimes, this will lead to confusion when we inadvertantly get a login shell, and find out that our configuration from
~/.bashrc is not loaded. This is why many people put something like the following in their
[[ -r ~/.bashrc ]] && source ~/.bashrc
This test whether
.bashrc is readable and then sources it.
Why You Sometimes Want a Login Shell
When you switch users using
su you will take the environment of the calling user with you. To prevent this, you should use
su - which is short for
su --login. This acts like a clean login for a new user, so the environment will not be cluttered with values from the calling user. Just as before, a login shell will read
/etc/profile and the
.bash_profile of the user you are switching to, but not its
.bashrc. This post on StackOverflow shows why you might want to prefer to start with a clean environment (spoiler: your $PATH might be “poisened”).
In this article we saw that the main difference between a login and a nonlogin shell are the configuration files that are read upon startup. We then looked at what the benefits are of a login shell over a nonlogin shell.