我正在执行以下管道:
tar -c directory | pv -T -c -B 2G | gzip -c9 | pv -T -c -B 2G | split -b 1G - /mnt/usbStick/f.tar.gz_
这个想法是将 >4GB 的目录 gzip 到一个大型 FAT32 格式(可靠地仅支持 <2GB 文件)USB 记忆棒上。
split
只是将a切成.gz
1GB的块。
pv
用作管道缓冲区(每个 2GB),主要是为了防止gzip
在遇到压缩性差的数据时发生限制,并且输出压缩数据的速度比 U 盘写入速度快。
问题:
当另一个 1GB 部分完成时,split
刷新并关闭文件。在刷新完成之前它不会开始写入下一部分,因此它停止接受输入。
我预计第二个 2GB 缓冲区此时会开始填满,但一切都停止了。系统总体上还远未死亡,但gzip
停止使用 CPU,甚至pv
停止更新其输出。从后半部分我得出结论,所有 IO 都已停止,甚至管道也是如此。 (如果我是错的,请证明我错了。)(我错了,只是特定的管道停滞了。)
所以问题是,为什么它会这样工作以及如何解决它。
编辑
确实是pv
它的错,buffer
工作正常。 Ubuntu 16.04 中包含的构建最多只能使用 2048 个块,每个块最多 512KB ( buffer -m 1024m -s 512k
),但它们可以以菊花链方式形成更大的缓冲区。
答案1
由于pv
它只是一个监控工具,我猜它是一个使用同步IO的单线程程序。给定输入和输出以不同的速率运行,它将填充和清空其缓冲区以防止节流,但如果其中一个管道完全停止(在您的情况下它不split
接受输入),第二个实例也会在调用pv
中停止write
。然后gzip
将尝试输出更多数据,溢出管道缓冲区并停止,依此类推,直到整个管道停止。
尝试使用buffer
而不是pv
看看这是否有帮助。buffer
产生两个进程(一个用于输入,一个用于输出),并且即使输出完全停止,也应该保持管道运行。