如何通过 SSH 执行命令并保持连接打开?

如何通过 SSH 执行命令并保持连接打开?

当我跑步时

FOO=$(ssh -L 40000:localhost:40000 [email protected] cat /foo)

我得到了 的内容/foo,但随后它就断开了。

我想做的是以某种方式获取内容/foo并保持连接打开,以便端口 40000 仍然转发到同一服务器。这可能吗?

你可能会问,为什么不像这样发出两个 ssh 连接

FOO=$(ssh [email protected] cat /foo)
ssh -L 40000:localhost:40000 [email protected] -f -N

在我的情况下,我不能这样做的原因是因为 ip ( 1.2.3.4) 是一个负载均衡器,它将连接转发到多个随机后端。每次我通过 ssh1.2.3.4连接到不同的机器时,每台机器的内容/foo都不同。此外,我通过转发端口(40000)发送的数据取决于/foo.如果我抓取机器 A 上的内容/foo,然后通过端口 40000 将数据发送到机器 B,则事情不起作用。

答案1

您所描述的称为 SSH 多路复用。

我在 DevOps 设置中使用该设置来缓存与任何虚拟机的连接。

通过这种方式,我可以重复使用相同的连接长达 30 分钟/缓存该连接,而无需在每个新命令中重新协商整个 SSH 连接(并对用户进行身份验证)。

当我连续向虚拟机/服务器发送(多个)命令时,它极大地提高了我的速度。

设置在客户端完成,对于 30 分钟的缓存,设置可以/etc/ssh/ssh_config如下完成:

ControlPath ~/.ssh/cm-%r@%h:%p
  ControlMaster auto
  ControlPersist 30m

MaxSessions参数还ssh_config定义了允许同时连接多少个复用连接;默认值为 10。如果您需要更多同时缓存的连接,您可能需要更改它。

例如,对于最多 20 个缓存连接:

MaxSessions 20

有关更多信息,请参阅OpenSSH/Cookbook/多路复用

SSH 多路复用的优点是消除了创建新 TCP 连接的开销。
...
第二个及以后的连接将一遍又一遍地重用已建立的 TCP 连接,而不需要为每个新的 SSH 连接创建新的 TCP 连接。

另请参阅使用 SSH 多路复用

SSH 多路复用是通过单个 TCP 连接承载多个 SSH 会话的能力

如果没有多路复用,每次执行该命令时,您的 SSH 客户端都必须与远程主机建立新的 TCP 连接和新的 SSH 会话。通过多路复用,您可以将 SSH 配置为建立在特定时间段内保持活动状态的单个 TCP 连接,并通过该连接建立 SSH 会话。当对远程 SSH 主机重复运行命令时,这可能会导致速度增加。

最后,由于多路复用使客户端和服务器之间的 TCP 连接保持打开状态,因此只要缓存处于打开/活动状态,您就可以保证与负载均衡器中的同一台计算机进行通信。

答案2

有多种方法可以做到这一点,您可以尝试的一种是

 ssh -fT -L 40000:localhost:40000 [email protected] 'sleep 60'
 FOO=$(ssh root@localhost -p 40000 cat /foo)

休息一下就可以继续...

这里 -f 是将其置于后台, -T 是禁用 tty 分配。使用 sleep 命令使会话保持活动状态 60 秒并允许自行退出,可以修改或通过其他方式弥补。

例如,一个简单的方法是,保持会话处于活动状态,直到看到文件 /tmp/a.txt ,一旦完成工作,创建一个文件, while 循环将看到它并运行清理 rm /tmp/a .txt 并退出会话。

ssh -fT -L 40000:localhost:40000 [email protected] 'while [[ ! -f /tmp/a.txt ]] ; do sleep 2 ; done ; rm /tmp/a.txt'
FOO=$(ssh root@localhost -p 40000 cat /foo)
do you work..
ssh root@localhost -p 40000 touch /tmp/a.txt

您可以使用任何其他更适合您的条件来保持其活力。

答案3

一个简单的方法可能是将其添加到您的 .ssh/config 中:

Host someUserFriendlyName
  HostName 1.2.3.4
  User root
  LocalForward 40000 localhost:40000
  RequestTTY yes
  RemoteCommand cat /foo;bash -l

然后执行ssh someUserFriendlyName 就应该没问题了。

答案4

我用sshpass

使用本地计算机上的包管理器安装它

然后运行

sshpass -p 'YOUR_SSH_PASSWORD' [email protected] 'YOUR-COMMAND' 

相关内容