为什么有些命令在使用 ssh 执行时不加载用户环境? (而其他人则这样做)

为什么有些命令在使用 ssh 执行时不加载用户环境? (而其他人则这样做)

在目标机器(OS X El Capitan)上,我brew/usr/local/bin.当我尝试获取brew的路径时,我没有得到结果:

# ssh [email protected] -p 2222 which brew
#

故障排除:

  1. brew/usr/local/bin/通过以下方式正确执行ssh

    # ssh [email protected] -p 2222 ls -l /usr/local/bin/brew
    -rwxr-xr-x  1 vagrant  admin  656 Mar 20 10:05 /usr/local/bin/brew
    # ssh [email protected] -p 2222 /usr/local/bin/brew --version
    Homebrew 0.9.5 (git revision 3a41; last commit 2016-03-20)
    
  2. /usr/local/bin路径中有:

    # ssh [email protected] -p 2222 echo $PATH
    /usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/opt/local/bin:/opt/local/sbin
    
  3. which本身似乎没有问题:

    # ssh [email protected] -p 2222 which bash
    /bin/bash
    
  4. 此外,当以交互方式记录到机器时,我得到了预期的结果:

    # ssh [email protected] -p 2222
    Last login: Sun Mar 20 12:02:55 2016 from 10.0.2.2
    osx-pf:~ vagrant$ which brew
    /usr/local/bin/brew
    
  5. 最后which brew在命令替换表达式中起作用:

    # ssh [email protected] -p 2222 echo $(which brew)
    /usr/local/bin/brew
    
  6. echo在之前调用which brew会导致它给出正确的结果:

    # ssh [email protected] -p 2222 echo test ; which brew
    test
    /usr/local/bin/brew
    
  7. 显式调用 shell 来运行which brew并不会改变这种情况:

    # ssh [email protected] -p 2222 /bin/sh -c "which\ brew"
    # ssh [email protected] -p 2222 /bin/sh -c "which\ which"
    /usr/bin/which
    

    然而,显式调用/bin/sh(6) 中的“技巧”不再有效:

    # ssh [email protected] -p 2222 /bin/sh -c "echo\ test\ \;\ which\ brew"
    test
    #
    

为什么which brew直接作为 ssh 命令参数运行会失败?

为什么echo哪个外部命令/bin/echo看到正确PATH而看which不到?为什么按顺序运行两个命令会导致第二个命令使用第一个命令的环境?

是否可以确保在不参考(6)中未记录的(我认为)解决方法的情况下加载环境?

答案1

ssh [email protected] -p 2222 echo $PATH

您的本地系统PATH将在此处打印。您应该引用该变量以防止它被本地 shell 扩展:

ssh [email protected] -p 2222 'echo $PATH'

这同样适用于:

ssh [email protected] -p 2222 echo $(which brew)

至于:

ssh [email protected] -p 2222 echo test ; which brew

which brew在 SSH 命令结束后由本地 shell 运行。这就是为什么这不起作用:

ssh [email protected] -p 2222 /bin/sh -c "echo\ test\ \;\ which\ brew"

旁注:您不需要执行所有转义操作。


这里的问题可能是您要添加brew到您的PATHin .profile(或.bash_profile或一些类似的文件)中,该文件在登录外壳已开始。 SSH 仅在交互运行时启动登录 shell,而不是在被告知运行命令时启动。从man ssh:

 If command is specified, it is executed on the remote host instead of a login shell

你可以尝试:

ssh [email protected] -p 2222 bash -lc brew

答案2

当您直接从 ssh 运行命令时,您并不是“登录”,而只是运行命令。

一些 shell 脚本在您“登录”时运行 - ~/.bashrc、/etc/profile 等。

which使用环境变量 - 特别是$PATH- 可以在这些脚本之一中设置。没有$PATHwhich将不知道去哪里寻找。

另外,不会给你你所期望的 -在它到达 ssh 之前由 shell 解释 - 比较:与(注意 shell 扩展周围的单引号)。第一个将获取本地主机名,将其发送到远程主机进行回显。第二个将(字面意思)发送到远程 shell,并在那里进行扩展。ssh [email protected] -p 2222 echo $(which brew)$(which brew)ssh [email protected] -p 2222 echo $(hostname)ssh [email protected] -p 2222 echo '$(hostname)'$(hostname)

更新:我对此略有错误。

当您通过 ssh 运行命令时,ssh 会判断是否需要 shell(例如计算变量等)。如果不需要,则立即运行二进制程序。否则运行 bash,这可能会设置环境变量等。

这就是为什么(在你的评论中)brew --version 失败 - 你没有提到路径。当您 时echo...; brew --version,分号;是一个特殊的 shell 字符; ssh 通过运行 bash 来为您处理这个问题。

相关内容