我有一个脚本,它执行一个 Rake 远程任务,该任务对两个角色各执行一次。两个角色都是同一 Vagrant 实例上的用户。因此,本质上,该任务是并行打开到同一 VM 的两个 SSH 连接,并在每个连接上执行一些命令。我经常发现,当执行此任务时,它会产生以下错误:
ssh_exchange_identification: read: Connection reset by peer
但是,这只发生在我们的 Jenkins 从属节点上,即 Mac Mini。我想出了一个简单的示例来重现连接重置行为:
ssh root@vagrant-target "echo hello" & ssh root@vagrant-target "echo bye"
我还发现,即使我反复执行上述命令,也无法在具有相同 Vagrant 设置的本地 MacBook Pro 实例上重现错误。
两台机器的操作系统版本相同,SSH 版本也相同。我还使用 -vvv 运行了上述 ssh 命令,但没有看到任何明显的结果。唯一想到的是,我在 Jenkins 机器上看到了一些 sshd 进程,大概是 Jenkins 使用的:
jenkins 34394 0.1 0.0 2471700 840 ?? S 6:27PM 0:00.05 /usr/sbin/sshd -i
jenkins 35220 0.0 0.0 2470872 1284 ?? S 6:27PM 0:01.38 /usr/sbin/sshd -i
root 35218 0.0 0.0 2469596 2908 ?? S 6:27PM 0:00.04 /usr/sbin/sshd -i
有谁知道为什么这种行为会出现在一台机器上,而不会出现在另一台机器上?
答案1
您是否尝试过建立控制主连接?这将允许您通过单个连接多路复用多个 ssh 会话。
要设置控制主机使用
ssh -o "ControlMaster=yes" -o "ControlPath=~/.ssh/%r@%h:%p" root@server
-o “ControlMaster=yes” 告诉 ssh 此连接将成为主进程。控制路径是一个套接字,用于允许其他 ssh 会话通过此连接进行。
要让你的 ssh 使用控制路径,你只需要在单独的终端中使用。
ssh -o "ControlPath=~/.ssh/%r@%h:%p" root@server "cmds" & \
ssh -o "ControlPath=~/.ssh/%r@%h:%p" root@server "cmds"
如果这不能解决问题,您可以使用 -vvv 标志发布 ssh 的输出吗?