我在 中设置了我的环境.profile
。我的.profile
是幂等的.bash_profile
,并且.bashrc
、.kshrc
和.zshrc
所有源.profile
。这样,无论我使用什么与 Bourne 兼容的 shell,也无论 shell 是交互式 shell 还是登录 shell,我始终都会获得相同的环境。
这也适用于非交互式ssh(1)
使用,尽管我不确定具体原因。
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
然而,在少数系统上,这并不起作用。
iridium:aram$ ssh ci20 'env|grep ^PATH'
PATH=/usr/bin:/bin
我一直在尝试实现这个功能,但没有成功。我尝试过:
- 切换到另一个 shell 而不是 bash
- 在 sshd_config 中禁用 PAM
- 启用 PAM 后,在 /etc/environment 中设置 BASH_ENV
这些没有效果,看来无论 PAM 设置如何,/etc/environment 都根本不会被读取。
请不要建议我要么强制 bash 在 ssh 调用中处于交互状态,要么在 ssh 调用中手动获取环境,我正在尝试修复此处的根本问题。
在尝试调试此问题时,我学到了一些有关 bash 的知识。如果标准输入是套接字,bash 似乎将始终获取 bashrc,即使它是一个非交互式 shell。某些 OpenSSH 版本以这种方式启动 bash,但其他版本的标准输入是管道。此外,bash 中的代码会尝试检测它是否在 ssh 会话中启动,在这种情况下,它也会获取 bashrc,而不管交互状态如何,但在某些情况下,此代码在编译时被禁用。这些事实似乎与我的问题有关,但我不清楚如何解决我的问题。
答案1
我完全明白了问题所在。
sshd 应该真正创建一个非交互式登录会话,而不是非交互式非登录会话,但它没有这样做。Bash 会尽力检测 ssh 的使用情况,如果它认为它是由 sshd 启动的,它会获取 bashrc,无论它是交互式的还是登录的。只有 bash 会这样做。因为我一直在使用 bash,所以我一直依赖这种获取行为,即使它不适用于其他 shell。
它检测 ssh 的方法有两种。它检查 stdin 是否为套接字 (1),如果失败,它会查找一些 SSH_ 变量 (2)。最近,openssh 改变了它的工作方式,因此 (1) 将永远无法再工作,因为 stdin 现在是管道,而不是套接字。 (2) 在某些 Linux 发行版中启用,但在其他发行版中禁用。我一直在使用启用了它的发行版。
由于 bash 所做的事情太可怕了,而且无论如何这都不能可靠地工作,我现在在 ~/.ssh/environment 中设置 BASH_ENV,所以现在总是有效,但不幸的是我现在必须PermitUserEnvironment yes
设置sshd_config
...
还不清楚为什么我不能设置它/etc/environment
,所以它适用于所有用户。