5

I'm experiencing a strange behavior on some of our machines atm. At least, it seems strange to me and my colleagues and we didn't find any explanation for it :)

[edit 1]
Next paragraph seems to be wrong. See edit 2 at end.
We're using bash and zsh here. So, when SSHing into some of the zsh-default-machines (plain ssh login@host) which are configured to use zsh as default shell (with chsh -s /usr/bin/zsh), the then-opened shell is an interactive but non-login shell, regardless if we're already logged in on the respective machine or not.

In my understanding, SSHing into a machine should be starting a new user session on that machine, thus requiring the shell to be a login shell, right? Shouldn't that be the case for zsh, too?

When changing the default shell to bash on the machines, logging into the machine uses a login-shell.

Is this the normal behavior for zsh? Could it be changed? Or is it some misconfiguration?
[/edit 1]

[edit 2] Ok, according to the ZSH documentation you could easily test if it is a login shell or not:

$ if [[ -o login ]]; then; print yes; else; print no; fi

See: http://zsh.sourceforge.net/Guide/zshguide02.html

However, due to zsh man entry / documentation, zsh should source /etc/profile which in turn sources the scripts under /etc/profile.d/*.sh. My question above originated in the fact, that the scripts are not sourced and thus most of our environment variables and system configuration stuff isn't properly initialized. However, as described above - when we're using bash as default shell, /etc/profile and the scripts in the profile.d-folder are sourced.
[/edit 2]

[edit 3 - ANSWER] Thx @StéphaneChazelas for the answer in the comments below! It seems zsh is only sourcing /etc/profile when running in sh/ksh compatibility mode (see the respecitve man entry https://linux.die.net/man/1/zsh). As logging in via SSH doesn't trigger that compatibility mode, zsh doesn't necessarily source /etc/profile on it's own but have to be triggered via .zprofile [/edit 3]

System: OS: Ubuntu 18.04 zsh-5.4.2 with omz and some plugins activated.

Thank you!

| improve this question | | | | |
  • 1
    How are you testing whether it's a login shell or not? – terdon Aug 27 '19 at 11:37
  • 3
    how did you infer that zsh is not a login shell? Afaik a zsh login shell will not source ~/.profile but ~/.zprofile. – mosvy Aug 27 '19 at 11:38
  • What's the output of echo $options[login] $0 $SHLVL in the interactive shell you get upon ssh login@host? – Stéphane Chazelas Aug 27 '19 at 12:02
  • @mosvy, also ~/.zlogin (à la csh) – Stéphane Chazelas Aug 27 '19 at 12:04
  • @StéphaneChazelas Output is on -zsh 1 Anyway, I tried if [[ -o login ]]; then; print yes; else; print no; fi from the zsh manual, which showed me that in fact is a login shell. So, my fault. Sorry. But then, why are the scripts in /etc/profile.d are not sourced when logged in via ssh? According to the zsh man entry, /etc/profile should be parsed when logging into a login-shell? Any idea? – nightsparc Aug 28 '19 at 8:31
1

ZSH just works in this way. /etc/profile is NOT an init file for ZSH. ZSH uses /etc/zprofile and ~/.zprofile.

Init files for ZSH:

  1. /etc/zshenv
  2. ~/.zshenv
  3. login mode:
    1. /etc/zprofile
    2. ~/.zprofile
  4. interactive:
    1. /etc/zshrc
    2. ~/.zshrc
  5. login mode:
    1. /etc/zlogin
    2. ~/.zlogin

enter image description here

References

| improve this answer | | | | |
  • Oh, thanks for the flowchart and the informative links! – nightsparc Sep 12 '19 at 9:11
5

sshd runs a login shell when the client doesn't send any command to run. That's to mimic the behaviour of rsh which was calling the rlogind service instead of the rshd one when not given any command to run.

To tell the shell it is to be a login shell, like rlogind or login or telnetd, sshd starts your shell with an argv[0] that starts with a -.

Or course, zsh like every other shell understands it as well. If it didn't, it couldn't ever be invoked in login mode.

Here, the symptom that made you think you didn't get a login shell was because /etc/profile was not interpreted.

/etc/profile is the login session initialisation file for Bourne-like shells. Syntax in there is expected to be in the Bourne shell syntax (or possibly POSIX sh syntax as the Bourne shell is hardly ever used these days) and is read upon login by all the shells whose syntax is (mostly) backward compatible with the Bourne or POSIX sh syntax.

csh and tcsh which have a completely different syntax use /etc/csh.login instead. fish uses /etc/fish/config.fish (regardless of whether it's in login mode or not).

zsh's syntax is also not completely compatible with that of Bourne/POSIX, so by default, it doesn't read /etc/profile. Its configuration files in login mode are /etc/zsh/zprofile (or /etc/zprofile depending on how zsh was configured at build time) and /etc/zsh/zlogin (or /etc/zlogin) the latter being sourced after the zshrc.

zsh only sources /etc/profile when in sh or ksh emulation in which case its syntax is much closer to that of POSIX sh than in the default zsh emulation mode.

If you want zsh to source /etc/profile when in login mode, you'd need to add a source /etc/profile in /etc/zsh/zprofile, but you'd only want to do that when you have made sure the syntax of /etc/profile and any other file it sources is compatible with that of zsh.

Alternatively, you could add:

emulate sh -c 'source /etc/profile'

To /etc/zsh/zprofile. Then /etc/profile would be sourced in sh emulation mode (and functions declared in there would also retain the sh emulation mode).

| improve this answer | | | | |
  • Thank you very much for the detailed answer! :) – nightsparc Aug 28 '19 at 9:38
  • Ok, one more question out of curiosity ;) Do you also know why /etc/profile is sourced when opening a non-login shell (with terminator, xterm ...)? – nightsparc Aug 28 '19 at 12:14
  • @nightsparc, sourced by what shell? Note that some terminal emulators can be configured to start a login shell and some systems configure them like that by default. – Stéphane Chazelas Aug 28 '19 at 12:30
  • Sourced by zsh...maybe it's an Ubuntu (or Debian?) thing? /etc/profile is sourced whenever I'm starting a terminal emulator, regardless which one I'm using (I tried gnome-terminal, xterm uand terminator). Thats confusing, from your explanation above I'd assume that /etc/profile[.d] is only sourced when zshis forced to use the compatibility mode. Or, according to man zsh when it is invoked as sh or ksh...but why are the terminal emulators are invoking it as sh/ksh? And is there a way to change it? – nightsparc Aug 28 '19 at 15:11
  • @nightsparc, what makes you think it runs /etc/profile? /etc/profile would probably have been sourced when you logged in. So environment variables would be inherited by the terminal emulator and by the shells started in there. – Stéphane Chazelas Aug 28 '19 at 15:24

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.