![`ssh` 是登录 shell,但是 `ssh ` 不是吗?](https://linux22.com/image/1534506/%60ssh%60%20%E6%98%AF%E7%99%BB%E5%BD%95%20shell%EF%BC%8C%E4%BD%86%E6%98%AF%20%60ssh%20%60%20%E4%B8%8D%E6%98%AF%E5%90%97%EF%BC%9F.png)
我注意到,当我使用语法直接在 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。
我得出以下结论:
ssh <host>
来源.bash_profile
,而ssh <host> <command>
仅限来源.bashrc
,这意味着- 前者是登录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)或“sshd
command
读取-求值-打印“脚本语言模式;它们实现了许多人类友好的功能,例如能够使用退格键来纠正拼写错误。但它们的开销更大,并且(取决于配置)不允许任意数据未经修改地通过,因此 SSH 会在不会发生交互时避免使用它们。
有时 SSH 的命令/无命令启发式方法会出错;可以使用-t
和-T
开关覆盖它。例如,要登录远程计算机并立即重新连接暂停的screen
会话,您需要执行ssh -t host screen -R
;ssh host screen -R
这将导致screen
抱怨未连接到终端。我想不出你真正会遇到的情况想使用-T
,但只要你找到它,它就在那里。
答案3
首先你需要了解不同的类型,你可以阅读这个:
现在如果你打开你的 bashrc,你将会在开头看到以下内容:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
这意味着,该文件是否加载其中的代码取决于您如何访问系统。