从标准输入缓冲区提取 tar 时管道损坏

从标准输入缓冲区提取 tar 时管道损坏

我正在将文件从 LTO-7 磁带上的 tar 存档恢复到本地安装的网络共享。如果我直接恢复到共享,它的运行速度会非常慢(90 MB/s)。当我使用额外的缓冲区时,我获得的最大吞吐量为 280 MB/s。但是我收到管道损坏警告:

mbuffer -s 1M -m 2G -i /dev/st0 | tar -xf -
mbuffer: warning: error during output to <stdout>: Broken pipe

请注意,tar 存档最初是使用 2048 的块系数(即 1MB 块大小)编写的

我猜这意味着 tar 在接收到所有数据之前就退出了(也许缓冲区暂时为空并且 tar 认为数据已经结束?)。

  1. 我该如何解决这个问题?即如何确保 tar 等待从缓冲区接收到所有数据?

  2. 为什么首先需要缓冲?连接是10G,目标磁盘是非常快的RAID。导致增速放缓的根本原因是什么?

编辑 02/07/2020

我在 tar 命令中添加了阻塞因子,但警告没有出现。

mbuffer -s 1M -m 2G -i /dev/st0 | tar -x -b 2048 -f -

但我仍然想知道如果未指定,为什么我会收到管道损坏警告。

答案1

您的错误消息有一个简单的原因:您使用的 tar 实现在调用之前没有读取所有数据exit()

这是由于您没有告诉它真实的磁带块大小而造成的(正如您自己已经发现的那样)。

典型的磁带(QIC 磁带除外)都是阻塞的,为了获得更高的性能,建议使用较大的块大小。不建议与其他人交换大于 126 kB 的块大小,但对于备份,使用 1MB 作为块大小是可以的。

TAR另一侧也指定为面向工作块,默认块大小为10kB。

EOF存档的定义是TAR紧接在最后一个文件之后的两个归零的 512 块(这是tar需要新标头的位置)。

在 EOF 指示之后,归档处理停止,除非这两个归零块偶然出现在磁带数据的最后 10 kB 中,否则存在未读输入,这就是您收到损坏管道消息的原因。

如果您使用star,则 FIFO 位于内部tar,因此,磁带读取代码并且tar归档处理始终对磁带块大小具有相同的想法。除了速度star更快之外,这还避免了并非所有输入数据都从tar archive.

顺便说一句:为了实现最佳流传输,建议 FIFO 缓冲区大小能够以最大磁带速度持续 10-30 秒的数据。直到star完全增强以支持更大的 FIFO 之前,我建议您致电:

star fs=2000m ...

注:是30年以来的-fifo默认值。star另请注意,-shm不建议在 Linux 上使用类似的选项,因为该功能的内存量有限。

star绝对比任何其他实现都要快tar。但请记住,如果您使用的是COW类似的文件系统ZFS,或者您的操作系统具有较慢的内核缓冲实现,则建议在提取模式下fsync()通过禁用调用来提高速度。-no-fsync这使得star与其他实现一样“不可靠” tar;-) 因为无法知道文件在后台存储上是否安全,但这可以将在ZFS缓冲不良的传统文件系统上的提取速度提高 4 倍。ZFS然而并没有实现不良缓冲,而只是能够以高代价授予特定的文件系统状态。

相关内容