复制 ssh 并在一个会话中执行命令

Are*_*nim 22 ssh scp

可能的重复:
使用已经建立的 SSH 通道

这是我的同步脚本:

ssh user@remote.host /etc/init.d/some_service stop
scp user@remote.host:/var/some_service/events ./events
scp ./new_data user@remote.host:/var/some_service/new_data
ssh user@remote.host /etc/init.d/some_service start
Run Code Online (Sandbox Code Playgroud)

如您所见,它停止服务,使用 scp 执行一些副本并重新启动服务。

问题是:它连续“花费”了 4 个“类似”的 ssh 连接。

有没有办法使用一个物理 ssh 连接来完成所有工作?

小智 25

您可以考虑使用 ssh 连接共享:

Host *.some-domain
ControlMaster auto
ControlPath ~/.ssh/master-%r@%h:%p
Run Code Online (Sandbox Code Playgroud)

您只连接到目的地一次,并将 ssh 进程置于后台。然后执行其他命令,最终杀死第一个进程。

或者,您可以尝试在一个 ssh 连接中封装一系列操作。

例如,假设您有一个目录:

 mycommands
 |
 +- run
 +- new_data
Run Code Online (Sandbox Code Playgroud)

然后,您可以将此数据打包到 tar 中并将其发送到您的脚本:

tar cf - -C mycommands . | ssh localhost 'D=`mktemp -d`; tar xf - -C $D; $D/run'
Run Code Online (Sandbox Code Playgroud)

现在您的run脚本可以访问您的所有输入数据(这里我们只有new_data您的示例中的数据)。为了坚持你的例子,这里是 run脚本:

#!/bin/sh
BASE=`dirname $0`

/etc/init.d/some_service stop
cat /var/some_service/events

mv $BASE/new_data /var/some_service/new_data
/etc/init.d/some_service start

rm -rf $BASE
Run Code Online (Sandbox Code Playgroud)

所以,现在你只需要保存events文件:

tar cf - -C mycommands . | ssh localhost 'D=`mktemp -d`; tar xf - -C $D; $D/run' >./events
Run Code Online (Sandbox Code Playgroud)

更一般地说,您可以让run脚本生成一个 tar,然后通过管道ssh输入 tar 以在本地解压缩它。


小智 4

您可以将此逻辑移至目标服务器上运行的脚本,然后使用单个 SSH 命令执行它。想必这并不理想,否则你已经这样做了:)

您可以使用 SSH 主连接来降低打开新 SSH 连接的成本。这意味着您的第一个 SSH 命令将像平常一样打开一个新连接。与同一服务器的后续连接将重用此现有连接,从而节省创建三个附加连接的开销。

这里有一个很好的设置指南:http ://www.linuxjournal.com/content/speed-multiple-ssh-connections-same-server

  • 补充一点...您可以完成此操作,而无需实际将脚本复制到远程服务器...假设您的主服务器上有一个名为“sync.sh”的脚本。假设它包含停止和启动服务的命令,以及对 scp 所需文件的调用。您可以在远程服务器上执行此脚本,而无需使用以下命令将其复制到远程服务器: `ssh user@remote.host <sync.sh` 如果您不想在多个远程系统上管理脚本,这会很方便。我将其用于[硬件/库存收集](http://serverfault.com/questions/365238/documenting-server-de (3认同)