我正在尝试将多个输入文件/流连接成一个流(使用虚构命令stream-cat
),将该流通过管道传输到ssh
远程主机并在远程主机上将其分离回单独的文件/流(stream-sep
),如本例所示,用于演示仅用于:
stream-cat <( zfs send tank/vm@snapshot ) somefile.txt | ssh user@host "stream-sep >( zfs receive tank/vm@snapshot ) somefile.txt"
示例说明:zfs send
输出大量数据,其大小事先未知(这就是tar
无法处理的原因)。该数据流与常规文件的内容连接在一起somefile.txt
。生成的流通过管道输送到ssh
,在那里再次分离。第一个流通过管道传输到zfs receive
,而第二个流写入常规文件。
这样的程序应该通过读取块中的不可搜索流并始终写入块大小后跟数据来实现,直到到达流的末尾。开销将是最小的。
这样的程序已经存在了吗?
您所描述的是多路复用;需要协议的东西(即关于如何处理数据的正式规范)。
有很多方法可以做到这一点。例如,您会注意到您的计算机可以完美地同时通过 HTTP 下载多个文件——即使是从同一台服务器。该功能首先由 TCP 提供给您,作为传输协议,它允许在接收端发送和“分解”不同的流。
所以,TCP 已经提供了该功能,您可以简单地启动两个并发 SSH 连接并使用它!
当然,
cat somefile.txt | ssh … > somefile.txt
您可能只是使用scp somefile.txt user@host:somefile.txt
(它在后台使用 SSH,但不进行 shell 连接,而是使用 SSH 中内置的 SCP 层来复制文件),而不是稍微不优雅的 。您可以通过将以下内容添加到文件中来更快地建立第二个连接
~/.ssh/config
:这将告诉 SSH 尝试并重新使用一个 SSH 会话同时发送多个加密流(这适用于
scp
和ssh
的任意组合)。这些的粗略实现
stream-cat
可以stream-sep
很容易地写成perl
:#! /bin/sh -
或与脚本而不是函数相同sh
。(错误处理留给读者作为练习:-)。
stream-cat
发送最大为 32767 字节的记录,前缀为n
网络编码(大端)短,其最低位指示它是新流 (0) 的开始还是继续,其余位是大小。然后,例如:
所以在你的情况下:
在极少数情况下,不安全形式的
open
(此处也被使用<>
)-n
允许<file
以>file
只读或只写模式打开文件或|cmd
通过cmd|
管道输入/输出命令实际上很有用。使用那些
|cmd
/比你的/cmd|
更好,因为一次只有一个打开,所以你可以毫无问题地发送数千个单独的流。<(cmd)
>(cmd)