如何通过 scp 最好地复制大量小文件?

nmi*_*els 71 scp tar

我有一个目录,里面有几 GB 和几千个小文件。我想用 scp 在网络上复制它不止一次。源机器和目标机器上的 CPU 时间很便宜,但是单独复制每个文件所增加的网络开销是巨大的。我会将它 tar/gzip 并运送过来,但源计算机磁盘不足。

有没有办法tar -czf <output> <directory>将 scp的输出通过管道传输?如果没有,还有其他简单的解决方案吗?我的源机器很古老(SunOS),所以我不想在上面安装东西。

pdo*_*pdo 129

您可以通过 ssh 会话通过管道传输 tar:

$ tar czf - <files> | ssh user@host "cd /wherever && tar xvzf -"
Run Code Online (Sandbox Code Playgroud)

  • +1 焦油管解决方案。如果您有更多的带宽和更少的 CPU,您可以删除压缩标志(尽管 gzip 非常轻量级)。 (6认同)
  • 从未想过像这样使用 tar。嗯,这就是我来这里的原因! (3认同)
  • 这个命令可以稍微短一点:`$ tar cz &lt;files&gt; | ssh user@host "cd /wherever; tar xvz"` (3认同)
  • (@carlito) _GNU_ tar 省略 `f` 默认为 stdin 或 stdout,但(大多数?全部?)其他 tar 则不然。 (3认同)
  • 您可以删除压缩标志,而是在 SSH 中激活它(`~/.ssh/config` 中的`ssh -C` 或 `Compression yes`)。 (2认同)
  • @Greg 破折号是 POSIX 兼容软件中的一个约定,根据上下文表示 STDIN 或 STDOUT。第一个破折号表示“从/dev/stdin 读取”,第二个破折号——实际上是在远程主机上执行的——表示“/dev/stdin”。管道和 ssh 连接这两个进程。请参阅 https://unix.stackexchange.com/questions/16357/usage-of-dash-in-place-of-a-filename 了解更多信息。 (2认同)
  • 这样做时请记住,像这样使用 cd 并不完全安全,如果失败,文件将被转储到用户的主目录中。使用@forcefsk 的回答中描述的`-C` 选项更安全。或者使用`&amp;&amp;`代替`;` (2认同)
  • 或者相反,从服务器“拉”: `ssh user@host "tar cz files" | 焦油xvz` (2认同)

for*_*sck 24

使用 bzip2 压缩的 Tar 应该从网络和 CPU 上承担尽可能多的负载。

$ tar -C /path/to/src/dir -jcf - ./ | ssh user@server 'tar -C /path/to/dest/dir -jxf -'
Run Code Online (Sandbox Code Playgroud)

不使用,-v因为屏幕输出可能会减慢进程。但是,如果您想要详细的输出,请在 tar ( -jcvf)的本地端使用它,而不是在远程部分。

如果您在同一目标路径上重复复制,例如更新备份副本,则最好的选择是 rsync 和压缩。

$ rsync -az -e ssh /path/to/src/dir/ user@server:/path/to/dest/dir/
Run Code Online (Sandbox Code Playgroud)

请注意,src 和 dest 路径都以 / 结尾。同样,不要故意使用-v-P标志,如果需要详细输出,请添加它们。


pol*_*mon 20

use rsync,它使用SSH。

用法:

rsync -aPz /source/path destination.server:remote/path
Run Code Online (Sandbox Code Playgroud)

rsync 开关关心压缩和 I-Node 信息。-P显示每个文件的进度。

您可以使用scp -C启用压缩的 ,但如果可能,请使用rsync.

  • 客户端计算机上的这些操作不需要 sshd。 (2认同)

小智 8

@pdo 的回答很好,但是可以通过缓冲区和良好的压缩来提高速度并添加进度条。

通常网络是瓶颈,速度随时间变化。因此,它有助于在通过网络发送数据之前缓冲数据。这可以通过pv.

此外,通常可以通过适当的压缩算法来提高速度。Gzip(如上面使用的)是一种快速压缩算法,但一般来说 zstandard ( zstd) (对于高压缩比 LZMA/LZMA2 ( xz) 将压缩得更好,同时速度更快。新的 xz 和 zstd 已经内置了多核支持. 要使用多核的gzip,可以使用pigz。

以下是通过网络发送带有进度条、缓冲和 zstandard 压缩的数据的示例:

tar cf - . | pv -perabs $(du -sk . | cut -f 1)K | zstd -14 --long=31 -T0 | pv -qCB 512M | ssh user@host "cd /wherever && pv -qCB 512M | zstd -cd -T0 --long=31 | tar xf -"
Run Code Online (Sandbox Code Playgroud)

第一个pv是显示进度(p)、估计时间(e)、传输速率(r)、平均速率(a)、总传输字节数(b)。总大小du通过大小选项 ( s )估算并添加到其中。进度是在压缩和缓冲之前测量的,因此它不是很准确,但仍然很有帮助。

zstd与压缩设置14 一起使用。这个数字可以根据网络和 CPU 速度减少或增加,所以 zstd 比网络速度快一点。Haswell 3.2 GHz CPU 14上有四个内核,速度约为 120 MB/s。在示例中,使用了长模式31(使用 2 GB 窗口,需要大量 RAM,但非常好,例如压缩数据库转储)。在T0选项设置线程数量,以核心数量。应该知道,这些设置与长模式一起使用大量内存。

zstd 的一个问题是大多数操作系统不附带版本 >= 1.3.4。此版本对于适当的多核和长期支持是必要的。如果不可用,它可以从https://github.com/facebook/zstd编译和安装,只需make -j4 && sudo make install. 除了 zstd,还可以使用 xz 或 pigz。xz 很慢但压缩得很好(比慢速连接好),pigz/gzip 很快但压缩得不太好。 pv然后再次使用,但用于缓冲(q安静,C无拼接模式[总是需要缓冲]并B设置缓冲区大小)。

在这个例子中,接收端也使用了一个缓冲区。这通常是不必要的(因为解压和硬盘写入速度大部分时间都高于网络速度),但通常也不会造成伤害。


小智 5

或者,如果需要,您也可以以相反的方式进行。这就是通过网络拉出 tarball,而不是像建议的那样推送它。这并不能解决您问题的重复部分,而 rsync 是最好的选择,但可能有 tar 开关可以提供帮助。

所以在本地机器上:

ssh remote 'tar zcf - /etc/resolv.conf' | tar zxf -
Run Code Online (Sandbox Code Playgroud)

最好先进入正确的目录,否则必须在最后使用-Cun ing 命令上的开关。tar

只是在需要时提及这一点。这对我来说是因为在我的情况下,我的本地服务器位于 nat 之后,因此需要一些网络测试才能按照前面提到的方式做到这一点。