我正在使用以下命令从memcached转储给定键的压缩对象:
cat <(printf "\x1f\x8b\x08\x00\x00\x00\x00\x00") <(memccat CACHE-KEY) | gunzip
它打印值(一个 JSON),但最后会出现警告:
gzip:标准输入:文件意外结束
我相信它可能缺少最后 4 个字节的校验和 ( ADLER32
),但我不确定。
从Memcached缓存服务以纯文本格式转储压缩键值的正确方法是什么?
看起来结果memccat CACHE-KEY
是一个 zlib ( RFC 1950 ) 流。您为 gzip 流 ( RFC 1952 ) 提供了 gzip 标头的十个字节中的八个作为前缀,这导致gunzip
将两字节 zlib 标头作为 gzip 标头末尾缺少的两个字节吃掉。gunzip
然后期待它得到的放气流(RFC 1951),然后是它没有得到的gzip预告片。一个 gzip 尾部是 8 个字节,由 CRC-32 和未压缩数据的长度组成。相反,它正在获取 zlib 预告片,它是未压缩数据的四字节 Adler-32。
要满足 gunzip,您不需要给它 zlib 流的最后四个字节,而是将其替换为八个字节,其中包括您需要计算的未压缩数据的 CRC-32 和未压缩数据的长度. 不过这有点傻,因为这些事情的重点是对未压缩数据进行完整性检查。
您真正想要做的是将该 zlib 流解释为 zlib 流,这将在最后使用 Adler-32 作为完整性检查。您可以使用pigz来解码 zlib 流pigz -dz
,或者您可以使用 zlib 轻松编写自己的 zlib 解码器。在名为zpipe的示例目录中提供了一个示例。