curl --compressed 解压到一半报 23,检查多成员 gzip
--compressed已开启仍报23且只留首段时,核对多成员gzip。区分内容编码与压缩包,在正式8.22.0能力范围内保存原始正文并完整检查解码。
下载压缩日志时已经加了 --compressed,输出文件却只包含前半段,curl 随后报错误 23。磁盘可写并不排除这个错误:gzip 响应包含多个连续成员时,curl 的内容解码也可能以写错误结束,已保存的第一段不能作为完整结果继续使用。
正式 curl 8.22.0 仍不支持这类多成员 gzip 响应解码。某些输入边界下会给出 Multi-member gzip response not supported,但不能要求每次都出现同样的详细文字;单独的错误码 23 也不能证明根因一定是多成员。
先区分压缩包与 HTTP 内容编码
如果接口提供的资源本来就是一个 .gz 文件,通常应按下载契约保存压缩包。若服务返回 Content-Encoding: gzip,它说明 HTTP 正文经过了 gzip 内容编码;--compressed 会请求并尝试解码这种正文。
看 URL 扩展名不足以判断是哪一种。核对真实响应头、状态和预期数据,确认不是登录页、错误页、截断传输或输出路径问题。手工加 Accept-Encoding: gzip 只声明接受编码,本身不会开启 curl 自动解压。
gzip 格式允许成员连续排列。GNU gzip 能解出所有成员,所以“外部工具能解开”与“curl 自动内容解码成功”是两项不同能力。不能因 curl 当前不支持,就认定所有这种 gzip 文件都损坏。
可控服务优先给出兼容响应
如果自己管理服务端,可以让该端点发送单成员 gzip,或在允许且确认有效时返回 identity 正文。调整编码要保留内容、缓存变体和协商规则,不能只改一个响应头,却继续发送原来的压缩字节。
请求 identity 不保证服务器一定遵守。仍要检查实际 Content-Encoding 和完整数据,不能把返回的二进制当文本处理。升级到 8.22.0 也不会获得多成员自动解码,未发布补丁不能算当前程序的能力。
保存原始正文,再由支持的工具完整解码
无法改变服务时,可在获准的下载环境,把编码正文与响应头分开保存,再用 GNU gzip 检查与解码。先为本次数据选取未被占用的新路径,并确认预期下载及解压后的空间预算。例如:
curl -q --fail --show-error --max-time 120 \
-H 'Accept-Encoding: gzip' \
--dump-header response.headers \
--output response-body.gz \
'https://logs.example.com/export'
地址、期限和文件名均为示例。首参 -q 跳过默认 curl 配置文件,避免其中的自动解压选项干扰下载。这里没有 --compressed,保存的是编码正文;也不使用 -i 把 HTTP 头混进 gzip 文件。接口需要认证或自定义 CA 时,显式沿用已核实的安全配置,限制头文件和下载文件的读取权限。
先检查 curl 退出状态和 HTTP 结果,再核对响应确实是预期的 gzip 内容。失败时保留诊断,不把部分文件送给下游。如果服务实际返回 identity 或业务错误,应按其真实格式处理,不能仅按 .gz 后缀强行解压。
完整下载并核对响应后,在支持多成员的 GNU gzip 环境中分别执行:
gzip -t response-body.gz
gzip -dc response-body.gz > decoded-new.txt
第二条只在前一条成功后执行;输出必须是新的独立文件,不能与输入相同。再次检查解码退出状态,然后核对业务记录、尾部标记或已有的完整性信息。校验成功证明 gzip 流结构可读,不证明服务器本来就提供了所有业务记录。
不要把失败的 curl 与解压直接拼成只看末端状态的管道,也不要用 gzip --list 给出的最后一个成员大小证明全部解压大小。解压可能大幅扩张,按可信数据来源及环境资源限制处理,不无限重试或导入未经核对的部分结果。
失败输出不能冒充完成文件
原来的 --compressed 输出即使包含可读内容,也可能只有第一个成员。隔离并标记它,修复后重新取得完整数据;不能只补一个成功退出码,继续沿用旧文件。
复查用原接口和原业务校验,确认完整记录已经到齐。若临时改变了脚本的解码步骤,保留原配置并在撤回时一起恢复,避免再次开启 curl 自动解码后还多做一次外部解压。只清理本次确认为不用的输出,保留必要诊断和源数据。


