刷新 USB 闪存驱动器时整个管道停止

刷新 USB 闪存驱动器时整个管道停止

我正在执行以下管道: 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切成.gz1GB的块。

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产生两个进程(一个用于输入,一个用于输出),并且即使输出完全停止,也应该保持管道运行。

相关内容