将`cat` 管道传输到gzip 以获取大文件的资源占用较少的替代方案

Foo*_*Bar 6 cpu memory pipe gzip cat

我有一些文件,其中一些文件非常大(比如几个 GB),我需要将它们连接到一个大文件然后压缩它,所以是这样的:

cat file1 file2 file3 file4 | gzip > compress.gz
Run Code Online (Sandbox Code Playgroud)

这会在机器上产生极高的 CPU 和内存负载,甚至使其崩溃,因为它会cat产生几个 GB。

我不能使用 tar 档案,我真的需要一个由 gzip 压缩的大块。

如何以顺序方式生成相同的 gz 文件,以便我不必先使用cat几个 GB,但最终仍将所有文件保存在同一个 .gz 中?

Sté*_*las 9

cat不使用任何显着的 CPU 时间(除非可能涉及磁盘解密或解压缩,并考虑到cat从磁盘读取的过程)或内存。它只是读取文件的内容并在循环中以小块的形式将其写入管道。

但是,在这里,您不需要它。你可以这样做:

gzip -c file1 file2 file3 file4 > compress.gz
Run Code Online (Sandbox Code Playgroud)

(并不是说它会产生显着差异)。

您可以gzip使用该nice命令降低进程的优先级(wrt CPU 调度)。一些系统有一个ionice与 I/O 相同的命令。

nice -n 19 ionice -c idle pigz -c file1 file2 file3 file4 > compress.gz
Run Code Online (Sandbox Code Playgroud)

在 Linux 上运行并行版本,gzip对系统的影响尽可能小。

compress.gz不同的磁盘上(如果使用旋转存储)将使其更有效率。

如果系统有可用内存,则系统可以缓存该数据catgzip/pigz在内存中读取该数据。它会这样做,以防您再次需要该数据。在这个过程中,它可能会驱逐其他更有用的缓存数据。在这里,这些数据可能不需要可用。

使用 GNU dd,您可以使用iflag=nocache建议系统不要缓存数据:

for file in file1 file2 file3 file4; do
  ionice -c idle dd bs=128k status=none iflag=nocache < "$file"
done | nice pigz > compress.gz
Run Code Online (Sandbox Code Playgroud)

  • 请注意,`gzip -c file1 file2` **不**等价于`cat file1 file2 | gzip`。根据联机帮助页,在前一种情况下,“输出由一系列独立压缩的成员组成”。在后一种情况下,连接的输入被压缩为单个压缩对象。联机帮助页甚至继续说“要获得更好的压缩效果,请在压缩之前连接所有输入文件。” 所以我建议 OP 不切换到 `gzip -c etc...` 只是为了删除无论如何都很便宜的 `cat`。 (3认同)