Where is the login shell defined?

TL;DR:

  • Where is login shell defined? In /etc/passwd.
  • Are sudo su/sudo su -/sudo -i/sudo -s same ? No, they all spawn a shell but differently and in different contexts.
  • What does $SHELL do? Just tell your default shell, same as in /etc/passwd.

Actual Answer:

First of all, it's important to mention that shopt is bash-specific. For instance, I am mksh shell user, and it doesn't have shopt , just like ksh doesn't.

Next, what exactly login_shell is supposed to represent ? From man bash:

login_shell

The shell sets this option if it is started as a login shell

That's the key point. sudo -i , as you already know from previous answer you read, is supposed to simulate initial login. That's why shopt reports login_shell on for this option. Think of this as if sudo -i forces the shell to go through files that are supposed to appear only during a login process ( which don't get sourced by interactive shells).

In other cases, you already are running an instance of a shell, so it cannot be login shell in the first place, and the purpose of the options is different. sudo -s merely reads $SHELL (which is meant to represent your default shell as set in /etc/passwd) variable and runs it with root privilege. This is equivalent to doing sudo $SHELL or sudo mksh or sudo bash ( whichever you happen to use).

Remember I mentioned that I am mksh user ? Take a look at this:

$ bash --posix
bash-4.3$ sudo -s
[sudo] password for xieerqi: 

DIR:/xieerqi|01:53|skolodya@ubuntu:
$ id 
uid=0(root) gid=0(root) groups=0(root)

DIR:/xieerqi|01:53|skolodya@ubuntu:
$ echo $-
imsU

What you see is that sudo -s jumped from bash to my mksh shell, with the characteristic prompt I've set for it. And of course, since it is not a login action, for bash it would report that the shell is spawned as non - login shell instance. In my case, however, you see that $- doesn't have a letter l there, which would be there if that was a login shell instance.

Finally, the same idea applies to sudo su and sudo su -. Later one spawns login shell instance (i.e., specific files that are required for login will run) and former one spawns only interactive shells (i.e., login files don't run).

bash-4.3$ sudo su
[sudo] password for xieerqi: 
root@eagle:/home/xieerqi# shopt login_shell
login_shell     off
root@eagle:/home/xieerqi# exit
bash-4.3$ sudo su -
[sudo] password for xieerqi: 
$ shopt login_shell
login_shell     on

So technically, shopt login_shell has no relation to $SHELL whatsoever. Think of it this way: its purpose is to show how bash runs. $SHELL is supposed to reflect only what you have assigned in /etc/passwd.

As for the difference between login shell and non-login shell, it has been explained by highly-respected Gilles on unix.stackexchange.com in this answer.


Additional fun

Here's something fun you can try. As you may already know, a login shell will run .profile (and .bashrc since Ubuntu's .profile is configured to do so) , but non-logins hell will run only .bashrc file. So we can test with echo which of these commands runs a login shell and which doesn't, and we expect two lines of echo for login shell and only one for non-login.

$ echo "echo 'hi,i am .profile'"  >> .profile
$ echo "echo 'hi, i am .bashrc'" >> .bashrc
$ sudo -i
hi, i am .bashrc
hi,i am .profile
$ sudo su
hi, i am .bashrc
root@eagle:~# sudo su -
hi, i am .bashrc
hi,i am .profile
$ sudo -s
hi, i am .bashrc
root@eagle:~# 

Appropriately enough, those with two lines of output will have login_shell set to on.


As @Serg explains in this answer on how to tell what shell you are running, the SHELL variable is just the current user's default shell as read from /etc/passwd:

$ grep zanna /etc/passwd
zanna:x:1000:1000:Zanna,,,:/home/zanna:/bin/bash

so if I echo $SHELL it will always return /bin/bash:

$ zsh
% echo $SHELL
/bin/bash

Whether or not the shell is a login shell, is a shell option determined at the time the shell is started. The shell program stores this information along with all its other settings and variables. The shopt command provides a way to see this information and, if possible for the option in question, to set or unset it (this isn't the case for login_shell which, of course, depends on the process used to start the shell)

The sudo program's options determine how these different types of root shell will be started:

enter image description here