gzip -t 可以检测 100% 的截断下载错误吗?

gzip -t 可以检测 100% 的截断下载错误吗?

设想:单个 1g CSV.gz 正在写入 FTP 文件夹。与此同时,我的客户端计算机通过 sFTP 连接到该文件夹​​并尝试将其拉下。

:获取该文件后,无论我在客户端获得什么明显的长度,都可以gzip -t检测到部分文件并使其失败,无论截断发生在哪里?

我认为当片段突然结束时,解压缩或 -t'esting 将在 99% 的可能截断点上出错,但是 gz 结构是否具有干净的切割点,gzip 会在其中意外报告成功?

不在桌面上的缓解措施(因为如果其中之一正在发挥作用,我就不需要问上述问题。)

  1. 通过另一个网络请求获取文件长度或md5。
    1. 通过 FTP 轮询文件长度并不是很好,因为服务器可能会偶尔将块写入 zip 流。在批处理作业关闭文件句柄之前,如果将其误认为是完整的数据集,对我的分析来说将是致命的。
    2. 通过批处理作业给出最终文件长度或散列,就不再需要这个问题,但这给团队带来了实施负担,而团队(就这个问题而言)可能不存在。
  2. 我们无法通过安排一天中不同时间的读/写来避免竞争。
  3. 服务器未使用原子移动操作。
  4. 我不知道 CSV 行/列数;每个快照和每个集成都会发生变化。对于这个问题,也可以说被 gzip 压缩的文件是一个不透明的二进制 blob。
  5. 游戏中没有 client=>sFTP 网络错误。 (这些被捕获并处理;我关心的是读取在服务器的批处理作业期间仍然偶尔写入的文件。)
  6. 使用 RESTful API 代替 sFTP。

没有找到现有的SO

几个SO触及处理截断,但与需要在任何问题上可靠地使整个工作流程失败相比,处于有损可接受的环境中。 (我在医疗数据环境中进行计算,因此我宁愿让服务器停止并着火,也不愿传播错误的统计数据。)

答案1

gzip 格式的文件包含压缩数据的长度和未压缩数据的长度。然而,这是一种古老的格式,长度字段只有 32 位,因此现在它们被解释为长度模 2^32(即 4 GiB)。解压前,gzip检查压缩数据的校验和是否正确。解压后,gzip检查解压数据的校验和是否正确,以及解压数据的大小是否正确模2^32。

因此,如果压缩数据的大小(或解压缩数据的大小)小于 4 GiB,gzip 保证检测到截断的输入。但是,对于任意大小的文件,我看不出有任何理由说明这些检查就足够了。如果输入不是故意设计的,并且其长度以 4 GiB 为模均匀分布,则压缩长度和校验和匹配的可能性只有 1/2^64,此外,如果文件在多字节序列的中间或者未压缩数据的长度不匹配。 (这并不一定会将机会减少到 1/2^96,因为压缩长度模 2^32 和未压缩长度模 2^32 是相关的。)因此,只有很小的机会出现未检测到的错误,但它不是零,我确信它可能是故意制作的。

请注意,此分析仅适用于 gzip 压缩文件由单个流组成的情况。gunzip可以解压缩由多个串联流组成的文件,并且无法检测文件是否包含有效的流序列,但需要更多的流。但是,您的生产链可能不会生成多流文件:gzip它本身不会生成,您必须手动连接多个运行的输出,或者使用其他工具(pkzip?)。

服务器未使用原子移动操作。

不幸的是,我认为没有一种完全可靠的方法来检测错误,而无需该方法或在服务器完成写入后计算的外部元数据(长度或加密校验和)。

相关内容