16

I was reading difference between sudo -i/-s here. After using command shopt it is noted that all(sudo su/sudo -i/sudo -s) the $SHELL are providing same results, but shopt command results are different.

So, how is login and non login shell defined?

From where shopt get the result?

Why it is not related to $SHELL?

sudo su

givinv@87-109:~$ sudo su
root@87-109:/home/givinv# 
root@87-109:/home/givinv# 
root@87-109:/home/givinv# shopt -q login_shell && echo 'Login shell' || echo 'No login shell'
No login shell
root@87-109:/home/givinv# echo $SHELL
/bin/bash
root@87-109:/home/givinv# 
root@87-109:/home/givinv# exit
givinv@87-109:~$ 

sudo -i

givinv@87-109:~$ sudo -i
root@87-109:~# 
root@87-109:~# shopt -q login_shell && echo 'Login shell' || echo 'No login shell'
Login shell
root@87-109:~# echo $SHELL
/bin/bash
root@87-109:~# 

sudo -s

root@87-109:~# sudo -s
root@87-109:~# shopt -q login_shell && echo 'Login shell' || echo 'No login shell'
No login shell
root@87-109:~# echo $SHELL
/bin/bash
root@87-109:~# 
  • 7
    One problem is that "login shell" has two meanings: 1. It's an instance of a shell started in a specific way that does specific things (like reading .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, your shopt 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. – muru Nov 25 '16 at 10:40
  • 1
    @muru 's explanation is a good one. for example if you SSH into your computer from a remote machine. /usr/sbin/sshd on your system would fork a shell defined by $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 with if [[ -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 – the_velour_fog Nov 25 '16 at 11:17
17

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.

  • Thank you @Serg and @Zanna. Now about $SHELL and login_shell/non-login_shell got clarified. But from where shopt get details? Is it from echo $0 ? – prado Nov 25 '16 at 10:20
  • 1
    @prado I would say yes, since first character of $0 is used to designate whether or not a shell is a login shell, so if shopt would check that variable - sure, it's perfectly acceptable . However, there's probably more than meets the eye. shopt probably For this question, I don't have a hard answer, since I'm not familiar with bash's source code that well. – Sergiy Kolodyazhnyy Nov 25 '16 at 10:35
  • @prado Bash can be started as a login shell either by having the first character of $0 be -, or by using the -l option. – muru Nov 25 '16 at 10:37
  • @prado you can read about bash's invocation and options in the man page. for example the SHELL BUILTIN COMMAND's section says login_shell The shell sets this option if it is started as a login shell (see INVOCATION above). The value may not be changed. so the shopt login_shell seems to be one way bash lets you find out - programmatically how to know how it was started. the another way would be [[ -o login ]] – the_velour_fog Nov 25 '16 at 10:40
11

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

  • 1
    Good explanation. I think you've explained what shopt and login_shell are supposed to represent far better that in my answer. – Sergiy Kolodyazhnyy Nov 25 '16 at 9:25
  • @Serg thanks :) I think your explanation is more thorough :) – Zanna Nov 25 '16 at 9:42
3

man bash:

A login shell is one whose first character of argument zero is a -, or one started with the --login option.

man login:

The value for $HOME, $SHELL [...] are set according to the appropriate fields in the password entry.

In short:

  • A shell is a login shell if it was invoked as a login shell.
  • The environment variable $SHELL is set by login or by the invoking program, for example su. The shell itself does not set it.
  • shopt shows the shell options currently in effect.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.