A login shell is the first process that executes under your user ID when you log in for an interactive session. The login process tells the shell to behave as a login shell with a convention: passing argument 0, which is normally the name of the shell executable, with a -
character prepended (e.g. -bash
whereas it would normally be bash
. Login shells typically read a file that does things like setting environment variables: /etc/profile
and ~/.profile
for the traditional Bourne shell, ~/.bash_profile
additionally for bash†, /etc/zprofile
and ~/.zprofile
for zsh†, /etc/csh.login
and ~/.login
for csh, etc.
When you log in on a text console, or through SSH, or with su -
, you get an interactive login shell. When you log in in graphical mode (on an X display manager), you don't get a login shell, instead you get a session manager or a window manager.
It's rare to run a non-interactive login shell, but some X settings do that when you log in with a display manager, so as to arrange to read the profile files. Other settings (this depends on the distribution and on the display manager) read /etc/profile
and ~/.profile
explicitly, or don't read them. Another way to get a non-interactive login shell is to log in remotely with a command passed through standard input which is not a terminal, e.g. ssh example.com <my-script-which-is-stored-locally
(as opposed to ssh example.com my-script-which-is-on-the-remote-machine
, which runs a non-interactive, non-login shell).
When you start a shell in a terminal in an existing session (screen, X terminal, Emacs terminal buffer, a shell inside another, etc.), you get an interactive, non-login shell. That shell might read a shell configuration file (~/.bashrc
for bash invoked as bash
, /etc/zshrc
and ~/.zshrc
for zsh, /etc/csh.cshrc
and ~/.cshrc
for csh, the file indicated by the ENV
variable for POSIX/XSI-compliant shells such as dash, ksh, and bash when invoked as sh
, $ENV
if set and ~/.mkshrc
for mksh, etc.).
When a shell runs a script or a command passed on its command line, it's a non-interactive, non-login shell. Such shells run all the time: it's very common that when a program calls another program, it really runs a tiny script in a shell to invoke that other program. Some shells read a startup file in this case (bash runs the file indicated by the BASH_ENV
variable, zsh runs /etc/zshenv
and ~/.zshenv
), but this is risky: the shell can be invoked in all sorts of contexts, and there's hardly anything you can do that might not break something.
† I'm simplifying a little, see the manual for the gory details.
The login is the core concept in jargon--login shell.
There are four stages abstracted to describe linux work:Init, Getty, Login , Shell.
Here login is a program, which gets the username as a parameter, and prompts the user for the password.
On local side:
vim /tmp/shell.sh
shopt login_shell
On server side(my vps server):
vim /tmp/shell.sh
shopt login_shell
1.non-interactive login shell
general format: ssh example.com <my-script-which-is-stored-locally
ssh root@vps_ip < /tmp/shell.sh
Pseudo-terminal will not be allocated because stdin is not a terminal.
login_shell on
More clearly
ssh -t -t root@vps_ip < /tmp/shell.sh
Last login: Wed Mar 8 03:16:00 2017 from vps_ip
root@localhost:~$
root@localhost:~$ shopt login_shell
login_shell on
The interpreter on local side break ssh -t -t root@vps_ip < /tmp/shell.sh
into two parts.
1.ssh -t -t root@vps_ip
login program accept root as user on the vps,logined.
2./tmp/shell.sh
the script on the local side passed as a parameter into interpreter on remote side ,and executed.
It is non-interactive login shell during the process.
2.non-interactive non-login shell
general format:ssh example.com my-script-which-is-stored-on-remote-machine
debian8@hwy:~$ssh root@vps_ip '/bin/bash /tmp/shell.sh'
login_shell off
debian8@hwy:~$
It is non-interactive non-login shell during the process.
Some hack trick can make it display as login shell.
debian8@hwy:~$ssh root@vps_ip '/bin/bash --login /tmp/shell.sh'
login_shell on
debian8@hwy:~$
The vps server does not be logined after the whole command ssh root@vps_ip '/bin/bash --login /tmp/shell.sh' performed.
The login_shell on displayed no meaning,it logined but vps server closed connection ,logined out.
Gilles's conclusions on non-interactive login shell and non-interactive non-login shell is right.
Best Answer
The idea is that a user should have (at most) one login shell per host. (Perhaps I should say, one login shell per host per terminal — if you are simultaneously logged in to a host through multiple terminals, you would expect to have multiple login shells.) This would typically (always?) be the first shell you get upon logging in (hence the name). So, this scheme allows you to specify actions that you want to happen only once per login and things that you want to happen every time you start a new (interactive) shell.
Normally, every other shell you run after logging in will be a descendant (a child of a child of a child …) of the login shell, and therefore will inherit many settings (environment variables,
umask
, etc.) from the login shell. And, accordingly, the idea is that the login initialization files (.login
,.profile
, etc.) should set the settings that are inheritable, and let.bashrc
(or whatever else you use) handle the ones that aren’t (set
,shopt
, non-exported shell variables, etc.)Another notion is that the login initialization files (and only they) should do “heavy lifting”, i.e., resource-intensive actions. For example, you might want to have certain processes running in the background whenever you’re logged in (but only one copy (instance) of them). You might want to have some status information (e.g.,
df
orwho
) displayed when you login, but not every time you start a new interactive shell. Especially if you have an interactive program/dialog (i.e., one that demands input from you) that you want to run every time you login, you probably don’t want to have it run every time you start a new shell. As an extreme example, twenty years ago Solaris logged you in to a single, non-graphical, non-windowed shell. (I believe that it has changed since then.) It was the job of.login
or.profile
(or whatever) to start the windowing system, with a command likestartx
. (This was useful partly because there were multiple windowing systems available. Different users had different preferences. Some users used different systems in different situations, and we had a dialog in our.profile
that asked “Which windowing system do you want to use today?”) Obviously, you wouldn’t want that to run every time you opened a new window or typedsh
.It’s been ages since I’ve used anything other than
bash
except for edge cases. (For example, I write scripts with#!/bin/sh
, so on some systems, my scripts run withdash
, and on others they run withbash
in POSIX mode. A few times a year I runcsh
/tcsh
for a few minutes to see how it handles something, or to answer a question.) If you use multiple shells (e.g.,bash
andzsh
) on a daily basis, your patterns may be different. If your primary shell (as defined in/etc/passwd
) isbash
, you might want to invoke azsh
login shell, and then perhaps invoke some interactive non-loginzsh
shells subordinate to that. You should probably avoid having a login shell that is subordinate to another login shell of the same type.As mentioned in Difference between Login Shell and Non-Login Shell?, the OS X Terminal application runs a login shell, so a typical user will typically have several “login shells” running simultaneously. This is a somewhat different model from the one I have described above, and may require the user to rethink what he does in his
.login
or.profile
(or whatever) file. I don’t know whether the OS X developers have documented their rationale for this design decision. But I can imagine a situation in which this would be useful. There was a time when I habitually opened a handful of shell windows when I logged in, and I would set them to different text and background colors (by writing ANSI escape sequences to the screen) to help me keep track of which was which. Terminal colors are an example of something that is not inherited by children-of-children, but does persist within a window. So this is the sort of thing that you would want to do every time you started a new Terminal window, but not every time you start a new interactive shell.