我有一个用例,其中我只需要将文件的一些字节(可以以 GB 为单位)上传到 SFTP 服务器,而不是整个文件。使用 SFTP PUT 命令,将上传整个文件,而不是一些字节。
我不想读取文件,然后将其制作成一个较小的文件,然后将整个较小的文件上传到 SFTP。如果要上传的字节数以 GB 为单位,这可能会占用大量内存。所以,放弃这个选项。
有没有其他方法可以使用 SFTP(可能使用 -o 来使用 ssh 选项)命令来执行此操作。也许像scp:如何仅复制文件的最后 10%?
请提出建议
答案1
标准 OpenSSHsftp
客户端不支持部分上传。
如果服务器运行的是常规 Linux,那么您可以直接将数据传送到 SSH 连接,而无需使用 SFTP:
$ tail -c 2G ~/bigfile | ssh myserver "cat > smallchunk"
(这里tail -c 2G
只是一个输出文件最后 2 GB 的示例命令。请根据需要进行替换 - 如果您想要前 X 个字节,则需要使用head
,如果您想要中间的字节,head|tail
则可以使用 或 的某种组合dd
。)
可选改进:您可以插入“pv”来显示进度条。
$ tail -c 2G ~/bigfile | pv | ssh myserver "cat > smallchunk"
如果你做需要 SFTP,那么lftp
可以通过上传命名管道:
在某处创建一个命名管道:
$ mkfifo /tmp/pipe
运行一个命令,获取您想要的任何字节,并将它们写入命名管道:
$ tail -c 2G ~/bigfile > /tmp/pipe &
一旦尝试写入管道,命令将立即暂停。(这与
|
上例中的无名管道完全相同 - 写入过程将暂停,直到读取过程从管道中读取所有内容,每次 4kB。因此让它&
在后台发生。)要求 lftp 上传管道:
$ lftp sftp://myserver lftp> put -o smallchunk /tmp/pipe 2G bytes transferred
为了清楚了解管道:这里再次是示例 1...
$ tail -c 2G ~/bigfile | ssh myserver "cat > smallchunk"
...下面是使用示例 2 中的“mkfifo”重写的示例 1:
$ mkfifo /tmp/pipe
$ tail -c 2G ~/bigfile > /tmp/pipe &
$ ssh myserver "cat > smallchunk" < /tmp/pipe
这两种管道的工作方式相同:它们使用管道将一个写入进程连接到一个读取进程。命名管道和无名管道都有一个 4 kB 的缓冲区;每次缓冲区填满时,写入进程就会暂停,直到读取进程获取数据。