为什么 ssh 远程命令的 $PATH 与交互式 shell 的不同?

为什么 ssh 远程命令的 $PATH 与交互式 shell 的不同?

我有一个用户没有对任何点文件中的 $PATH 进行任何修改:它正是系统默认设置。从登录 shell:

$ ssh example.com
[email protected]:~$ cat /tmp/hello.hs
#!/bin/bash

echo "$SHELL"
echo "$PATH"

[email protected]:~$ /tmp/hello.hs
/bin/bash
/usr/local/bin:/usr/bin:/bin

正如在 中指定的/etc/profile。我发现这相当出乎意料:

$ ssh example.com '/tmp/hello.sh'
/bin/bash       
/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games

~/.bashrc就像我说的,在和 中都没有修改 $PATH /etc/bash.bashrc。也没有~/.ssh/environmentssh(1)声明环境变量PATH

设置为默认 PATH,如编译 ssh 时所指定的。

此主题来自 StackOverflow 和这个邮件列表这篇文章建议我应该只需修改 /etc/profile(其中一个 shell 启动文件等)即可影响给定命令的 $PATH。

这里发生了什么?

答案1

来自ssh(1)手册页:“如果指定了命令,它将在远程主机上执行,而不是在登录 shell 上执行。”

简而言之,当您实际登录到计算机时,bash 将作为登录 shell 启动并加载适当的文件,当您远程连接并发出命令时,它将代替 bash 运行,这意味着这些文件不会加载。您可以su -l -c在 ssh 的命令部分使用或类似命令来解决此问题。

在某些情况下,我也看到了-tssh 工作(分配 tty)的参数。

编辑1
我认为您找到的 PATH 信息表明,默认路径(除非我们覆盖它)是编译到 sshd 中的路径。我确保我的 /etc/profile、/etc/bash*、本地点文件等没有任何 PATH 信息,然后我登录时仍然有 PATH。我在 sshd 中搜索了这个并在那里找到了它。所以手册页是这样说的:

ahnberg@remote$ strings /usr/sbin/sshd | grep -i x11 | grep bin
/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games

然后我将其添加PATH=$PATH:/my/test到远程文件的最顶部.bashrc,并再次检查:

ahnberg@local$ ssh ahnberg@remote "env | grep PATH"
PATH=/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games:/my/test

所以我绝对可以影响它,并且默认 PATH 是编译到 sshd 中的那个。:)

答案2

通过运行以下命令,我能够让 ssh 使用远程路径运行命令:

ssh dist@d6 "bash --login -c 'env'"

这里,env 可以替换为您所需的任何命令。

我已经授权密钥,因此不需要密码来运行命令或 ssh。

答案3

我想出了一个不同的解决方案来解决这个问题。我个人的偏好是创建新的配置文件,而不是更改现有的配置文件。这样我可以更轻松地从默认配置中排除更改。

以下是 的内容/etc/profile.d/ssh_login.sh

#!/bin/sh
if [ "$SSH_CONNECTION" ]; then
    echo "User '$USER' logged in from '${SSH_CONNECTION%% *}'"
    . /etc/environment
fi

使用dropbear代替openssh-server(这也应该适用于 openssh),当我远程登录时,SSH_CONNECTION 变量会自动设置。我创建了一个新的 shell 配置文件配置来检测 SSH 登录,在屏幕上显示一些信息,最重要的是,从中加载全局环境设置/etc/environment以替换编译的值。请注意,这只会影响交互式 SSH shell,而不会影响远程命令执行。

或者,如果您使用 openssh 并且始终想要加载全局环境,无论它是否是交互式 shell,您都可以~/.ssh/像这样放置符号链接:

ln -s /etc/environment ~/.ssh/environment

然后您需要启用PermitUserEnvironment中的选项/etc/sshd/sshd_config。但请仅对受信任的用户执行此操作,因为这可以使他们使用 LD_PRELOAD 等机制绕过某些配置中的访问限制。请参阅了解man sshd_config更多信息,特别是如何使用Match块将选项限制到特定用户/组。

答案4

如果您想要加载配置文件路径,请尝试:

#!/bin/bash -i

在脚本顶部。这样,运行脚本时,shell 处于交互模式。

当 bash 作为交互式登录 shell 或使用 --login 选项作为非交互式 shell 调用时,它首先从文件 /etc/profile 中读取并执行命令(如果该文件存在)。读取该文件后,它会按顺序查找 ~/.bash_profile、~/.bash_login 和 ~/.profile,然后从第一个存在且可读的文件中读取并执行命令。启动 shell 时可以使用 --noprofile 选项来禁止此行为。

http://linux.die.net/man/1/bash

相关内容