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
.
.profile
or equivalents), and 2. It's the shell that's supposed to started at login for a user, as defined in/etc/passwd
or equivalent.$SHELL
contains the latter, yourshopt
outputs deal with the former. Typically, when the shell in (2) is started at login, it is started in the specific way needed for (1), hence the conflation of meanings.$SHELL
(and connect it to a pseudo terminal) which in turn is defined in your /etc/passwd entry. this shell is a login shell and can be tested withif [[ -o login ]]; then echo "I am a login shell"; fi
. being a login shell it would perform those tasks appropriate to a new session. e.g. source~/.zprofile
or similar which would possibly set environment variables and any custom shell code you might want to run at this time