情况如下:
- 我正在使用 sftp 将一个大文件从客户端 A 上传到服务器。
- 我还需要通过 ssh 从服务器将该文件下载到客户端 B。
我想做的是当客户端 A 仍在上传时开始从服务器到客户端 B 的传输。
完成此任务的最佳方法/工具是什么?
更新:
到目前为止的答案很有趣——我一定会阅读并测试它们。对于不依赖于控制客户端 A 上传文件方式的答案,可加分。 (即,我们从客户端 A 知道的唯一信息是该文件正在写入已知的文件名。)
答案1
对于单个文件,而不是使用 SFTP,您可以使用cat
或pv
在发送端通过 ssh 管道传输该文件,并tee
在中间服务器上使用,将数据发送到那里的文件,并通过另一端的另一个 ssh 链接发送副本只是将数据写入文件。我将把所需的确切巫毒作为练习留给读者,因为我现在没有时间玩(抱歉)。仅当第二个目标可通过 SSH 公开访问时,此方法才有效,但您将其描述为客户端计算机时,情况可能并非如此。
另一种方法,较少“运行和等待”,但可能更容易,它rsync
在服务器和客户端 B 之间使用。第一次运行此方法时,它可能会获得数据的部分副本,但您可以重新运行之后它会获取更多数据(客户端 1-> 服务器传输完成后最后一次运行)。仅当服务器在 SFTP 传输期间将数据直接放入正确的文件名中时,此操作才会起作用(有时您会看到数据进入临时文件,然后在文件完全传输后对其进行重命名 - 这样做是为了使文件更新更加原子,但会使 rsync 想法无法使用)。您还可以使用 rsync 代替 scp 进行 C1->S 传输(如果您使用该--inplace
选项来避免上述问题) - 使用 rsync 还可以为您提供保护,防止在 C1->Server 连接遇到问题时需要重新发送所有内容在大型传输期间(rsync --inplace -a --progress <source> <dest>
当 rsync 可用时,我倾向于使用scp/sftp 来代替 scp/sftp,以实现“传输恢复”行为)。
总结以上内容,运行:
rsync --inplace -a --progress <source> user@server:/<destination_file_or_folder>
在 client1 上然后运行
rsync --inplace -a --progress user@server:/<destination_file_or_folder> <destination_on_cli2>
在 client2 上重复,直到第一次传输完成(然后再次运行以确保您已获得所有内容)。rsync
非常擅长只传输更新位置所需的绝对最小值,而不是每次都传输全部。对于偏执狂,您可能需要将该--checksum
选项添加到 rsync 命令(对于大文件,这将花费更多的 CPU 时间,但不会导致传输更多的数据,除非需要),并且为了速度,--compress
如果数据您正在传输的格式尚未压缩。
答案2
我现在无法尝试,所以这很可能会失败:我的想法是这样的:挂载文件到达客户端 B 的目录,例如使用 sshfs 到客户端 b 文件系统中的 /mnt/server 。然后
tail -c +0 -f /mnt/server/thefileinquestion > ~/finalfile
答案3
我认为这应该有效:
user@clientA:~$ cat file | ssh server "cat > dest"
进而
user@clientB:~$ ssh server "tail +0 -f dest" > file
如果您想查看吞吐量,请添加 pv 命令。
答案4
我遇到的情况需要像原始海报所要求的解决方案。我正在一个位置的计算机上录制一场曲棍球比赛,并且想在另一个位置的电视上观看。两个位置之间的链接允许复制速度约为 1.3Mb/s,录制视频速度约为 1.5Mb/s。所以,我想在文件开始录制时复制它。这样我3个小时的游戏就可以在大约3.5小时内完成复制。所以,我会在开始录制时复制它,并可以在开始录制 30 分钟后开始观看。然后我就可以不间断地、几乎实时地观看它。也就是说,只要我可以让它在写入新文件时进行复制。 rsync 和 scp 等工具的问题在于,当您启动复制时,它们会查看文件的大小,一旦复制了该数量的数据,它就会退出;即使文件在该复制过程中增长了一倍以上。而且,如果我只是在循环中使用 rsync 来复制它,一旦它停止,当下一个 rsync 完成时,它会重建目标文件,这会杀死我的视频播放器,我必须重新开始观看它并快进到我所在的位置在程序中突然杀掉它的时候。我想要一个更好的解决方案,但一直找不到,所以我拼凑了这个:
dd if=2031_20160514030000.mpg |
pv --size 4653819304 |
ssh -C -c arcfour,blowfish-cbc -p 5555 myserver.com 'dd of=/media/TV/2031_20160514030000.mpg'
那么这有什么作用呢?
首先,我使用 dd 在文件增长时复制该文件。由于文件的增长速度快于 dd 通过网络发送的速度,因此 dd 永远不会到达文件末尾。接下来,我将其通过管道传输到“管道查看器 (pv)”,并根据这些文件通常有多大来估计文件的大小。这不是必需的,但我喜欢看到进度表。然后,我将流通过管道传输到我的 ssh 连接。 ssh 连接用于-C
压缩(以减少网络带宽并尝试加快速度),-c arcfour,blowfish-cbc
用于最便宜的加密(再次加快速度),这-p
是我在目的地使用的防火墙端口,以及ssh 最后在目标上运行 dd 命令,以在收到文件时重新创建该文件。我很高兴地说,这个解决方案效果很好。我可以在创建和复制文件的同时观看曲棍球比赛,只有很短的延迟。