`ssh` 是登录 shell,但是 `ssh ` 不是吗?

`ssh` 是登录 shell,但是 `ssh ` 不是吗?

我注意到,当我使用语法直接在 SSH 主机上运行命令时ssh <host> <command>,我看到了 的输出,但看不到(或).bashrc的输出。.bash_profile.profile

例如,如果我将以下命令放在两个文件的顶部,

echo ${BASH_SOURCE[0]}

并手动获取.bash_profile.bashrc依次获取),我会看到

$ . .bash_profile
.bash_profile
.bashrc

ssh <host>如果我使用命令的形式通过 SSH 远程登录此计算机,则会看到相同的输出。 (如果我.bash_profile暂时存放在其他地方,则这两行都不会回显。)

但是,如果我直接在远程机器上以ssh <host> <command>的形式执行命令ssh,则输出如下所示:

$ ssh <host> echo foo
/home/rlue/.bashrc
foo

.bash_profile我的理解是,和之间的区别.bashrc在于前者是为了登录 shell而后者是为了交互式、非登录 shell

我得出以下结论:

  1. ssh <host>来源.bash_profile,而
  2. ssh <host> <command>仅限来源.bashrc,这意味着
  3. 前者是登录shell,而后者不是。

这些结论正确吗?为什么被ssh <host> <command>视为交互式、非登录 shell?SSH 不是仍然需要登录远程机器才能执行命令吗?

答案1

OpenSSH(很可能是您正在运行的)决定是否创建登录 shell,并且仅当您未运行特定命令时才会这样做。来自man ssh

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

因此,是否要创建登录 shell 是 ssh 服务器的实现选择,如果您给出要运行的命令,它就不会运行。

虽然ssh确实执行了登录,但如果您让它执行命令并退出,那么它实际上更类似于创建一个 shell 来运行该命令,而不是获取登录环境。鉴于此,编写 OpenSSH 的人似乎决定将其视为此类任务。

他们创建了一个非交互式、非登录的 shell 来执行命令,因为这是在另一个上下文/shell 中运行命令的精神。不过,通常情况下,非交互式 shell 不会自动执行 source,而~/.bashrc这里显然发生了这种情况。 bash实际上是在试图帮助我们。来自文档

由远程 shell 守护进程调用

Bash 尝试确定何时将其标准输入连接到网络连接来运行,例如由远程 shell 守护程序(通常是 rshd)或安全 shell 守护程序 sshd 执行时。如果 Bash 确定它以这种方式运行,它会从 ~/.bashrc 读取并执行命令(如果该文件存在且可读)。如果以 sh 形式调用,它不会执行此操作。可以使用 --norc 选项来禁止此行为,可以使用 --rcfile 选项来强制读取另一个文件,但 rshd 和 sshd 通常都不会使用这些选项来调用 shell 或允许指定它们。

答案2

为什么这种行为的本质比 shell 要低:(ssh host“登录 shell” 的情况)使用伪终端在远程主机上,在sshd服务器进程和 shell 之间进行通信;在和ssh host command之间使用管道。伪终端对于交互式使用命令解释器(如 shell)或“sshdcommand读取-求值-打印“脚本语言模式;它们实现了许多人类友好的功能,例如能够使用退格键来纠正拼写错误。但它们的开销更大,并且(取决于配置)不允许任意数据未经修改地通过,因此 SSH 会在不会发生交互时避免使用它们。

有时 SSH 的命令/无命令启发式方法会出错;可以使用-t-T开关覆盖它。例如,要登录远程计算机并立即重新连接暂停的screen会话,您需要执行ssh -t host screen -Rssh host screen -R这将导致screen抱怨未连接到终端。我想不出你真正会遇到的情况使用-T,但只要你找到它,它就在那里。

答案3

首先你需要了解不同的类型,你可以阅读这个:

https://unix.stackexchange.com/questions/170493/login-non-login-and-interactive-non-interactive-shells

现在如果你打开你的 bashrc,你将会在开头看到以下内容:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

这意味着,该文件是否加载其中的代码取决于您如何访问系统。

相关内容