DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

GNU tar 追加 tar.gz 文件时报 Cannot update compressed archives

GNU tar 不能对压缩归档直接执行追加或更新。将完整输入合并为一次创建,或先收集未压缩归档再压缩,避免重复 -c 覆盖和误删源文件。

循环把文件加入同一个 .tar.gz 或 .tar.bz2 时,GNU tar 可能报:

tar: Cannot update compressed archives

例如将追加选项 -r 与 gzip 压缩选项 -z 一起使用,并不会得到“向压缩包增加一个文件”的效果。GNU tar 不支持直接对压缩归档执行追加、更新、删除成员或归档拼接;换成 bzip2 或 xz 也没有消除这个限制。

下面针对 GNU tar。处理前保留现有归档和源文件,不要把打包命令与自动删除源文件串成一条流程。

有完整源文件时,一次创建新的压缩归档

如果所有待归档文件仍然在磁盘上,最直接的处理是把它们交给同一次创建操作。假设 /srv/project 中有 report-a.txt 和 report-b.txt:

tar -czf /srv/backups/reports-new.tar.gz \
  -C /srv/project -- report-a.txt report-b.txt

这里是创建一份新的完整归档,不是在旧压缩包上追加。-- 结束选项解析,两个成员都相对于 -C 指定的目录。

如果改用绝对路径后看到 Removing leading / 提示,可查看归档成员路径与恢复位置的关系。这项路径处理不会解除压缩归档不能直接追加的限制。

示例中的输出目录需要已存在且可写,输出文件名必须是本次专用且尚不存在的名称,源文件也必须换成实际要保留的完整集合。输出应放在源目录之外。若使用 -c 重复写同一个旧归档,每次创建都可能覆盖它;不能把循环里的 -r 机械改成 -c。

对于 .tar.bz2,相应的创建选项是 -cjf;.tar.xz 使用 -cJf。这些选项改变压缩方式,不改变压缩归档不能直接更新的规则。

必须分批收集时,先保留未压缩 tar

如果输入分两批到达,可以先创建真正的未压缩 tar,再追加第二批。下面仍是假设独立测试路径、全新输出文件、已有源文件的演示:

tar -cf /srv/backups/reports-staging-new.tar \
  -C /srv/project -- report-a.txt &&
tar -rf /srv/backups/reports-staging-new.tar \
  -C /srv/project -- report-b.txt

第一步的 -c 建立合法 tar 结构,第二步的 -r 才是追加。touch 只会创建空文件,不等于建立一个有效的 tar 归档。&& 使创建失败后不会继续追加,但第二步失败时仍需停止后续处理、保留源文件并检查错误。

追加也不是按名称替换已有成员。如果再次追加同名文件,归档可能包含多个同名成员;按顺序恢复时,后面的成员通常覆盖前面的内容。需要唯一名称或明确版本的备份,应先确定完整文件清单,避免依靠重复追加实现更新。

完成收集并检查未压缩归档后,再压缩一次。使用 GNU gzip 时,可以保留中间 tar,让压缩结果写入新文件:

(
  set -C
  gzip -c /srv/backups/reports-staging-new.tar > /srv/backups/reports-final-new.tar.gz
) && gzip -t /srv/backups/reports-final-new.tar.gz

这段使用 POSIX shell 语法;set -C 在子 shell 内启用禁止覆盖已有普通文件的重定向保护,输出仍应选在受控备份目录,不能把它当成不可信共享目录的完整安全隔离。gzip -c 保留输入 tar,gzip -t 仅检查压缩数据完整性。失败时不要使用可能不完整的新输出,应保留中间 tar,排除错误后用另一个新文件名重试。

如果仍保有完整源集合,也可以回到上一节一次重建压缩归档。不要再对生成后的压缩文件运行 tar -r 或 tar -u。

只有旧压缩包时,不要覆盖它试错

若旧成员已经没有其他副本,重新打包现有少量文件会遗漏旧内容。此时应保留旧压缩包,准备独立工作空间,在副本上解压压缩层得到未压缩 tar,再追加并重新压缩;这需要容纳未压缩归档和新输出的空间。

解压压缩层得到 .tar 与把全部成员解包到目录是两回事。后者涉及文件路径、权限、链接和同名覆盖,不能把未知归档直接展开到业务目录。空间不足、原归档校验失败或无法确认成员完整时,应停止转换,不应删除旧包来腾空间。

分别检查归档结构与备份内容

对新创建的 gzip 归档,可以只读列出成员;对中间未压缩归档,则省略 -z:

tar -tzf /srv/backups/reports-new.tar.gz
tar -tf /srv/backups/reports-staging-new.tar

检查清单是否包含全部预期文件,是否出现意外的重复成员,并检查命令状态与错误输出。能够列出名称不代表内容与源文件一致;正式替换备份前,还应在隔离目录验证恢复和必要的内容、属性。

采用新的输出名称能保留明确的回退点。只有新归档完成校验并满足原备份要求后,才按既有保留策略处理旧副本。打包过程中删除源文件,会把一次归档错误升级成无法补救的数据丢失。