快速版本:
ssh
在我的台式机和scp
笔记本电脑上工作。从我的 android 手机上的 termuxssh
可以工作,但scp
不能。在这种情况下,我收到有关“连接已关闭”的错误。
扩展版
最初,当我问这个问题时,我在连接到我的 Fedora Linux 机器时,在我的 android 手机上从 termux 运行 scp 时遇到了这个问题。而且我一直很困惑,ssh
所以我提供了很多调试信息。因为后来我了解到这个问题与 termux 完全无关,而与 OpenSSH 版本有关,所以我试图清理很多无关的信息转储并使其更易于访问,同时仍然保留相关的错误消息以更好地进行 seo 匹配.
设备:
- 设备 A(计算机):运行 openssh.x86_64 8.7p1-3.fc35 的 Fedora 35
- 设备 B(计算机):运行 openssh.x86_64 8.7p1-3.fc35 的 Fedora 35
- device C (phone): android上的termux (我原来抓不到openssh版本,估计是v8.8或更高版本)
计算机 A 和 B 具有基本相同sshd_config
的文件,所有 3 个基本相同的~/.ssh/config
文件内容。
问题:
A->B、B->A、C->A 和 C->B 之间的 ssh 连接都工作正常。我对从任何一台计算机连接到我的手机都不感兴趣,并且从未在其上配置过 sshd,因此没有测试这种情况。
但是,对于通过 ssh 运行的 scp,我遇到了以下问题: A->B 和 B->A 工作,而 C->A 和 C->B 失败,出现以下错误:
$ scp -rp "[email protected]:/home/desktop-user/Pictures/test.jpg" .
scp: Connection closed
调试:
- 大量验证 ssh 文件权限和所有权、
~/.ssh/config
设置等。没有明显问题。 - 我(暂时)在 A 和 B 上禁用了 SELinux 和 firewalld,但仍然遇到同样的问题。
- 根据这篇文章,我将自定义的 id_rsa(和 id_rsa.pub)文件名重命名为使用默认名称,并编辑了相应的
~/.ssh/config
定义。没变。 - 我没有尝试(从 C 中)尝试从远程接收/拉取文件,而是尝试将文件推送/发送到远程。没变。
- 从 C 开始,我确保所有软件包都是最新的。没变。
- 从 C 中,我运行
scp
带有标志的命令-v
以提供详细的调试信息。在编辑哈希等之后,我添加到pastebin。我看到的主要内容是密钥似乎已被接受,但最后一行表明“debug1:退出状态 127”。在线结果似乎表明scp
主机上不存在......但就我而言,它是。所以还是没有变化。
主机的 sshd 配置
同样,A 和 B 具有基本相同的配置
# grep -Pv '^\s*(#|$)' /etc/ssh/sshd_config
Include /etc/ssh/sshd_config.d/*.conf
Port 22
Ciphers [email protected],aes256-ctr
LoginGraceTime 1m
PermitRootLogin no
MaxAuthTries 4
MaxSessions 6
PermitEmptyPasswords no
ChallengeResponseAuthentication no
UsePAM yes
X11Forwarding yes
PrintMotd no
UseDNS yes
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
Protocol 2
DenyUsers root docker-user
MACs [email protected],hmac-sha2-512,[email protected],hmac-sha2-256
KexAlgorithms diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha256
快速版本 (TL;DR)
更新:对于那些只想要快速而肮脏且阅读最少的人。
知道:
sftp
会在紧要关头工作,但它处理符号链接的复制方式与此不同,scp
因此不要只是将其放入脚本中作为替代。更好用rsync
。递归地将目录从远程复制到本地:
递归地将目录从本地复制到远程:
这也适用于多条路径,例如
根本原因
经过大量的在线搜索,我终于在这里找到了答案——感谢 manjaro 论坛用户 zbe 和 canyue980 找到了最初的修复程序并让我了解了实际情况。
引用canyue980:
确实,将我的命令从:
至:
它就像一个冠军。会留下这个,希望它可以帮助别人。
-O 的安全含义
使用的安全含义
-O
(在 OLD 中是“哦” - 不是零):根据 openssh 8.8 的发行说明,听起来主要风险是:对于习惯了旧命令并手动运行或通过家庭计算机上受信任的脚本运行的人来说,我个人认为这不会是一个很大的风险。但是您的风险评估/用例可能会有所不同——尤其是对于使用未经验证/不受信任的脚本的业务系统或设置。这似乎是某些情况,因为RHEL 9 正在弃用 scp 协议,理由是:
从上面的发行说明和链接,以及arch wiki 上的说明来看,似乎其意图是完全弃用SCP(例如协议),转而支持
sftp
和rsync
(见下文)之类的替代方案。我不清楚该scp
命令的预期未来是什么,尤其是在短期内,但它似乎是合理的,甚至可能在未来也会被弃用。推荐的替代品
要在脚本中使用
sftp
和rsync
作为插入式替换,可能rsync
是更容易的插入式替换,因为它不需要对主机进行任何更改,而至少在 Fedora 35sftp
中是这样。sftp
只要您可以sftp <user>@<host_ip>
像连接一样连接,下面的命令应该可以正常工作ssh
(以这种方式连接会将您置于sftp
“shell”中。要退出,请使用exit
)。否则,您可能必须在主机上启用它。对于 Fedora 35,该过程如下:sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.$(date +'%F_%T').bak
sudo sed -Ei 's~^(Subsystem[ \t]+sftp[ \t]+)(/usr/lib/openssh/sftp-server)~#\1\2\n\1internal-sftp~g' /etc/ssh/sshd_config
sudo systemctl restart sshd
完成后,您应该会看到类似这样的内容(例如,应该注释掉 sftp 服务器行,并添加一个带有 internal-sftp 的新行来代替它):
如果您需要提高安全性,还可以使用组和 chroot 来限制这一点,如此处和此处所示。
注意:
scp
默认情况下,复制符号链接的内容而不是将它们作为符号链接。-l
Rsync 允许您通过使用复制为符号链接或-L
复制符号链接引用的内容来控制此行为。(-a
存档)选项将默认为-l
,除非-L
还指定。会将符号链接复制为链接(例如,不sftp
复制指向的内容)并且在撰写本文时不提供用于控制此行为的选项。您可以通过分别查看和下的选项的文档来验证这一点。-r
man scp
man sftp
以下是一些大致等效命令的示例,它们都应该通过 SSH 并获取您的
~/.ssh/config
设置和身份:递归地将目录从远程复制到本地:
递归地将目录从本地复制到远程:
更正 sftp 语法
编辑:2022 年 9 月 13 日:今天在重新测试时注意到我的命令
sftp
出现错误,因此我将它们从上面移出并添加一些免责声明。由于我上面提到的在涉及符号链接时它们如何处理复制方面存在差异,我个人并不推荐sftp
作为替代品。scp
我对使用它作为脚本中的替代品特别感兴趣。如果您只需要交互模式,请不要介意为 制作“批处理”指令文件
sftp
,或者已经rsync
安装在您将使用的所有机器上,那么您可能不需要走这么远。我下面的笔记部分基于这个答案,我做了一些额外的测试。我在这里最大的抱怨(除了
sftp
使用不同的语法进行上传和下载)是非常糟糕的文档。看一下man sftp
,语法根本没有记录(这意味着虽然该工具可以以非交互方式使用,但它只记录在批处理和交互模式下使用,并且在支持时跳出这些用例,但没有记录)。手册页没有像许多 GNU 工具那样提供常见用法的示例,甚至没有提供更详细文档的网站。并sftp -h
提供少于手册页。从字面上看,如果不是这样的搜索引擎和网站,我会完全放弃sftp
作为一种选择。1.本地拉取(例如从本地终端,从远程下载文件到本地)
这主要是直截了当的,
scp
除了上面提到的差异(例如符号链接)和稍微不同的语法之外,它的工作方式有些相似。并且其中一种变体将产生交互式提示。2.本地推送(例如从本地终端,从本地上传文件到远程)
首先,如果您只是尝试反转参数,就像我原来的答案一样,那么您将收到连接错误。为什么不让
sftp
上传语法和下载语法一致?你的猜测和我的一样好......我本来会是这种方法的忠实粉丝。但是,如果您尝试一下,会发生以下情况(注意:此输出来自运行 Fedora 35 的 2 台机器,并且正确配置了 sshscp
并且rsync ... -e ssh
工作正常,并且不提示进行身份验证)。根据我上面链接的答案,正确的方法是如下
我在我的脚本中发现使用类似的语法进行下载,例如
不那么令人困惑,但以上所有内容都应该有效。
要一次复制多个路径,可以使用数组(或者您可以创建一个批处理文件
put
,在单独的行中列出每个命令并将其传递给sftp
使用该-b <batchfile>
选项)。2022 年 10 月 10 日更新:在遇到包含空格的副本的一些问题后
rsync
,我更新了使用该-s
选项的命令(在此答案中解释)但是,我注意到 rsync 的不同之处
scp
和sftp
(关于处理空格)的一个观察结果是,scp
对于包含内部引号的路径总是很好,例如然而,如果你在 中这样做
rsync
,你会得到一个错误:The fix for this is quite easy but maybe not intuitive if you are using to using the inner quoted path syntax from
scp
like I was: just use-s
and get rid of the inner quotes.rsync
is smart enough to handle it and it just works.So the above command that had an error, would just be changed to:
And all should be good (assuming
scp
works fine for the same path).