/etc/profile.d 和“ssh -t”

/etc/profile.d 和“ssh -t”

我想在远程机器上运行一个脚本。简单的解决方案是这样的:

ssh remote1 some-script

这个方法一直有效,直到远程脚本不想连接到另一个remote2需要交互式身份验证的远程机器(),就像这个(在这种情况下remote2只能通过以下方式访问):remote1

ssh remote1 "ssh remote2 some-script"

解决该问题的方法是使用-tssh 选项。

ssh -t remote1 "ssh remote2 some-script"

这有效,但如果我使用它,我会遇到问题(some-script可能会执行进一步的 ssh 命令):

ssh -t remote1 some-script

我发现有些环境变量没有设置,而这些变量是在我不使用该-t选项时设置的。这些环境变量是在脚本中设置的/etc/profile.d。我猜想如果使用该选项,这些脚本由于某种原因不会运行-t,但如果我不使用它,这些脚本就会运行。

这是什么原因?有什么办法可以解决这个问题吗?我正在使用 SUSE Linux(版本 10)。

编辑:我做了一些额外的研究。我将一些输出行放到了以下位置:

  • 在一个文件中/etc/profile.d
  • ~/.bash_profile文件之前不存在)
  • ~/.bashrc文件之前不存在)

然后我检查了几种情况下我得到的输出以及输出顺序(我检查的环境变量是$PATH):

  • ssh remote1profile.d.bashrc.bash_profile$PATH好的。
  • ssh -t remote1profile.d.bashrc.bash_profile$PATH好的。
  • ssh remote1 echo '$PATH':仅此而已.bashrc$PATH好的。
  • ssh -t remote1 echo '$PATH':无脚本输出。NOK $PATH

现在我真的不明白发生了什么。如果我运行一个交互式 shell,一切似乎都运行良好(尽管我发现~/.bashrc在 之前包含很奇怪~/.bash_profile)。如果我启动一个没有 的非交互式 shell -t,配置文件脚本似乎不会运行,但环境变量已设置。如果我用 启动非交互式 shell -t,则配置文件脚本不会运行,环境变量也不会设置。有人对此有解释吗?

答案1

我没有找到问题的原因。也许它特定于平台(SLES 10 或我使用的变体)。我找到了一种解决方法:

ssh -t remote1 "/bin/bash --login -c some-script"

这将强制运行配置文件脚本的登录 shell。

答案2

所有问题的答案都在 bash 手册页的“INVOCATION”部分中:

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

当登录 shell 退出时,bash 会从文件 ~/.bash_logout 读取并执行命令(如果存在)。

当启动非登录 shell 的交互式 shell 时,如果 ~/.bashrc 文件存在,bash 将从该文件中读取并执行命令。可以使用 --norc 选项禁止此操作。--rcfile 文件选项将强制 bash 从文件而不是 ~/.bashrc 中读取并执行命令。

正如您所见,交互式 shell 仅提供来源.bashrc,并且通常.bash_profile从那里获取来源,这解释了您所看到的顺序。

很多时候,这些文件还具有仅为交互式 shell 解析某些部分([[ $- == *i* ]])的条件,这可以解释为什么某些部分对于非交互式 shell 来说可能缺失。

答案3

和...之间的不同

ssh remote1 echo '$PATH'

ssh -t remote1 echo '$PATH'

bash 手册页中也有解释:

Bash 尝试确定何时将其标准输入连接到网络连接来运行,例如由远程 shell 守护程序(通常是rshd)或安全 shell 守护程序执行时。如果 bash 确定它以这种方式运行,它将从[我假设应该读取] 和sshd读取并执行命令(如果这些文件存在且可读)。~/.bashrc/etc/bash.bashrc~/.bashrc

在第一个例子中,bash的标准输入连接到网络连接,因此它运行~/.bashrc。在第二个例子中,它的标准输入来自伪终端,因此它不运行。

相关内容