3

I set my environment in .profile. My .profile is idempotent and .bash_profile, .bashrc, .kshrc and .zshrc all source .profile. That way I always get the same environment regardless on what bourne-compatible shell I use, and regardless on whether the shell is interactive or a login shell.

This works with non-interactive ssh(1) usage too, though I am not sure exactly why.

iridium:aram$ ssh sunos.mgk.ro 'env|grep ^PATH'
PATH=.:/home/aram/bin:/home/aram/bin/sunos:/home/aram/bin/sunos/amd64:/home/aram/bin/sunos/386:/home/aram/go/bin:/opt/local/bin:/opt/local/sbin:/usr/gnu/bin:/usr/bin:/sbin:/usr/sbin:/usr/sfw/bin:/usr/local/bin:/usr/local/sbin:/home/aram/plan9/bin
iridium:aram$ ssh iridium 'env|grep ^PATH'
PATH=.:/Users/aram/bin:/Users/aram/bin/darwin:/Users/aram/bin/darwin/amd64:/Users/aram/bin/darwin/386:/Users/aram/go/bin:/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/pkg/bin:/usr/pkg/sbin:/usr/local/plan9/bin
iridium:aram$ ssh crimson 'env|grep ^PATH'
PATH=.:/home/aram/bin:/home/aram/bin/linux:/home/aram/bin/linux/amd64:/home/aram/bin/linux/386:/bin:/usr/bin:/sbin:/usr/sbin:/usr/games:/usr/local/bin:/usr/local/sbin

On a minority of systems, this doesn't work, however.

iridium:aram$ ssh ci20 'env|grep ^PATH'
PATH=/usr/bin:/bin

I have been trying to make this work, but without success. I have tried:

  • switch to another shell instead of bash
  • disable PAM in sshd_config
  • with PAM enabled, set BASH_ENV in /etc/environment

These had no effect, it appears /etc/environment is not read at all regardless of PAM setting.

Please don't suggest that I either should force bash to be interactive in my ssh invocation, or that I should manually source the environment in my ssh invocation, I'm trying to fix the underlying problem here.

While trying to debug this issues I have learned a few things about bash. It appears bash will always source bashrc, even if it's a non-interactive shell, if the standard input is a socket. Some OpenSSH versions start bash that way, but in other version standard input is a pipe. Also there's code in bash that tries to detect if it's started in a ssh session, and in that case it will also source bashrc regardless of interactive status, but in some cases this code is disabled at compile time. These facts seem related to my problem, but it is not clear how I can solve my problem.

3

I have fully understood what the problem is.

Sshd should really make a non-interactive login session, instead of a non-interactive non-login session, but it doesn't. Bash tries really hard to detect ssh usage, and sources bashrc if it thinks it's started by sshd, regardless whether it's interactive or login. Only bash does this. Because I have been using bash, I have been relying on this sourcing behavior, even though it didn't work with other shells.

There are two ways it detects ssh. It looks whether stdin is a socket (1), and if that fails, it looks for some SSH_ variables (2). Not that recently, openssh changed the way it works, so (1) will never work again because stdin is now a pipe, not a socket. (2) is enabled in some Linux distros, but disabled in others. I have been using distros where it was enabled.

Since what bash did was horrid, and since this doesn't work reliably anyway, I'm now setting BASH_ENV in ~/.ssh/environment, so that now always works, but unfortunately I now have to set PermitUserEnvironment yes in sshd_config...

Also it's unclear why I can't set it in /etc/environment, so it works for all users.

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.