Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: 'login' vs 'interactive' ?

On Tue, 18 Nov 2014 11:11:46 -0500
TJ Luoma <luomat@xxxxxxxxx> wrote:
> 1) Can someone explain the difference between 'login' and
> 'interactive' in these two examples:
> if [[ -o login ]]; then
>   echo "I'm a login shell"
> fi
> if [[ -o interactive ]]; then
>   echo "I'm interactive"
> fi

Overall, the differences are two-fold (i) how you got there (ii) what
the consequences are.

You might like to read
which I wrote some years ago but makes attempts in the right direction.

How you got there --- what makeas a shell a login shell --- is described
on page 108 of "From Bash to Z Shell".  Basically, it's done by
executive decision of whatever it is that's starting your shell.  That's
not very easy to summarise nowadays when there are so many ways of
starting the shell.

What makes a shell interactive is very roughly that the shell itself
thought it had an environment that looked like a terminal and couldn't
think of any reason why the user might not want it to use that terminal
(e.g. being passed a script is such a reason).

What the consequences are has got a lot to do with startup files, so
I've appended the bit from the FAQ (this is pretty much the only use of
being a login shell, apart from an explicit test like the one you've got

However, the shell bases a number of internal decisions on whether or
not it's interactive.  These are intended to be common sense, e.g. if
it's interactive you want the line editor and if it's not interactive
you don't.  Needless to say, it's not always that simple.

> 2) is 'login' vs 'interactive' similar to "every square is a rectangle
> but a rectangle is not necessarily a square"?
> As in "Every login shell is interactive, but an interactive shell is
> not necessarily a login shell"?

Not necessarily, in fact, because neither of the two points above is a
subset of the other.  For example, something managing the way your
window system starts may decide to launch the shell that sets up the
environment as a login shell, but without a terminal.

> 3) Imagine an alternate universe where zsh _automatically_ reads
> ~/.zshenv but NOT ~/.zshrc so you had to tell zsh to read ~/.zshrc as
> part of ~/.zshenv.
> Would the answer be:
> if [[ -o login ]]; then
>   source .zshrc
> fi
> or
> if [[ -o interactive ]]; then
>   source .zshrc
> fi

The second.  This actually is well-defined and even documented.  See below.

> 4) Anything else I should understand about these two?

Your counterfactual ~/.zshenv would also contain (being somewhat more,
but not necessarily completely, pedantic about associated tests):

if [[ -o login && -f ${ZDOTDIR:-$HOME}/.zlogin ]]; then
  source ${ZDOTDIR:-$HOME}/.zlogin

and there's likewise pseudo-code for .zlogout (but nowhere to put it
other than an EXIT trap).

FAQ excerpt follows.

3.2: In which startup file do I put...?

  When zsh starts up, there are four files you can change which it will
  run under various circumstances: .zshenv, .zprofile, .zshrc
  and .zlogin.  They are usually in your home directory, but the
  variable $ZDOTDIR may be set to alter that.  Here are a few simple
  hints about how to use them.  There are also files which the system
  administrator can set for all shells; you can avoid running all except
  /etc/zshenv by starting zsh with the -f option --- for this
  reason it is important for administrators to make sure /etc/zshenv
  is as brief as possible.

  The order in which the four files are searched (none of them _need_
  to exist) is the one just given.  However, .zprofile and .zlogin
  are only run when the shell is a login shell --- when you first login,
  of course, and whenever you start zsh with the -l option.  All
  login shells are interactive.  The order is the only difference
  between those; you should decide whether you need things set before or
  after .zshrc.  These files are a good place to set environment
  variables (i.e. `export' commands), since they are passed on to
  all shells without you having to set them again, and also to check
  that your terminal is set up properly (except that if you want to
  change settings for terminal emulator windows like xterm you will
  need to put those in .zshrc, since usually you do not get a login
  shell here).  

  The only file you can alter which is started with every zsh (unless
  you use the -f option) is .zshenv, so this is a good place to put
  things you want even if the shell is non-interactive: options for
  changing the syntax, like EXTENDED_GLOB, any changes to set with
  `limit', any more variables you want to make sure are set as for
  example $fpath to find functions.  You almost certainly do not
  want .zshenv to produce any output.  Some people prefer not to
  use .zshenv for setting options, as this affects scripts; but
  making zsh scripts portable usually requires special handling anyway.

  Finally, .zshrc is run for every interactive shell; that includes
  login shells, but also any other time you start up a shell, such as
  simply by typing `zsh' or opening a new terminal emulator window.
  This file is the place to change the editing behaviour via options or
  `bindkey', control how your history is saved, set aliases unless
  you want to use them in scripts too, and for any other clutter which
  can't be exported but you only use when interacting directly with the
  shell.  You probably don't want .zshrc to produce output, either,
  since there are occasions when this can be a problem, such as when
  using `rsh' from another host.  See 3.21 for what to put in .zshrc
  to save your history.


Messages sorted by: Reverse Date, Date, Thread, Author