I understand the basic difference between an interactive shell and a non-interactive shell. But what exactly differentiates a login shell from a non-login shell?
Can you give examples for uses of a non-login interactive shell?
I understand the basic difference between an interactive shell and a non-interactive shell. But what exactly differentiates a login shell from a non-login shell?
Can you give examples for uses of a non-login interactive shell?
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.
bash as a non-interactive login shell?
– Piotr Dobrogost
Jun 16 '13 at 8:47
FOO is an environment variable (i.e. .profile contains export FOO=something) then it's available to all subprocesses, including foo.sh. If you change .profile to export FOO=something_else then ./foo.sh will still print something until the next time you log in.
– Gilles
Oct 6 '16 at 15:13
To tell if you are in a login shell:
prompt> echo $0
-bash # "-" is the first character. Therefore, this is a login shell.
prompt> echo $0
bash # "-" is NOT the first character. This is NOT a login shell.
Information can be found in man bash (search for Invocation). Here is an excerpt:
A login shell is one whose first character of argument zero is a -, or one started with the --login option.
You can test this yourself. Anytime you SSH, you are using a login shell. For Example:
prompt> ssh user@localhost
fervor@localhost's password:
prompt> echo $0
-bash
The importance of using a login shell is the any settings in /home/user/.bash_profile will get executed. Here is a little more information if you are interested (from man bash)
"When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and
executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile,
~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable.
The --noprofile option may be used when the shell is started to inhibit this behavior."
In a login shell, argv[0][0] == '-'.
This is how it knows it's a login shell.
And then in some situations it behaves differently depending on its "login shell" status. E.g. a shell, that is not a login shell, would not execute a "logout" command.
man bash, with emphasis added, "A login shell is one whose first character of argument zero is a -, or one started with the --login option."
– Wildcard
Jan 23 '17 at 11:49
A shell started in a new terminal in a GUI would be an interactive non-login shell. It would source your .bashrc, but not your .profile, for example.