Linux 基础体系 · 第 49/85 篇。示例面向现代主流 Linux 发行版;发行版差异、权限和生产风险会明确说明。
Linux 归档与压缩:tar、gzip、xz、zstd、校验和和大文件
一、先区分归档、压缩和校验
**归档(archive)**是把多个文件及其目录结构、元数据组织成一个数据流或文件;**压缩(compression)**是利用数据中的重复模式减少数据量;**校验和(checksum)**是根据数据计算摘要,用于发现传输或存储过程中的变化。
tar 主要负责归档,gzip、xz 和 zstd 主要负责压缩。常见文件名:
backup.tar 仅归档
backup.tar.gz tar 归档后使用 gzip 压缩
backup.tar.xz tar 归档后使用 xz 压缩
backup.tar.zst tar 归档后使用 zstd 压缩
它们的处理顺序通常是:
多个文件
│
▼
tar 归档
│
▼
gzip / xz / zstd 压缩
│
▼
一个压缩归档文件
恢复时顺序相反:
压缩归档文件
│
▼
解压缩
│
▼
tar 解析归档
│
▼
恢复目录、文件和元数据
tar 本身通常不压缩。把 backup.tar.gz 称为“tar 压缩包”在日常交流中可以理解,但更准确的描述是“使用 gzip 压缩的 tar 归档”。
压缩率的定义
设原始数据大小为 ,压缩后大小为 ,压缩率可以表示为:
例如,原始数据为 100 MiB,压缩后为 40 MiB,则:
也可以使用节省比例:
此时节省比例为 60%。
压缩效果取决于数据本身。文本、JSON、日志通常包含大量重复模式;JPEG、MP4、ZIP 等已经压缩过的数据通常几乎不能继续压缩,甚至可能因为格式开销而略微变大。
二、tar 如何保存文件
1. tar 是顺序数据流
一个 tar 归档可以抽象为:
文件头 + 文件内容
文件头 + 文件内容
文件头 + 文件内容
结束标记
文件头中通常包含:
- 文件名;
- 文件类型;
- 文件大小;
- 权限;
- 用户 ID 和组 ID;
- 修改时间;
- 符号链接目标;
- 硬链接关系;
- 扩展属性、ACL 等扩展信息,取决于参数和实现。
tar 按顺序写入文件,因此创建归档时不需要为每个文件建立独立压缩流。多个文件之间的重复内容可以被压缩器共同利用,这通常比“先分别压缩每个文件,再打包”更有效。
例如,下面两个方案的压缩上下文不同:
方案 A:tar 多个日志文件,再整体 gzip
a.log + b.log + c.log -> tar -> gzip
方案 B:每个日志文件分别 gzip,再 tar
a.log -> a.gz
b.log -> b.gz
c.log -> c.gz
a.gz + b.gz + c.gz -> tar
方案 A 允许压缩器跨文件发现重复字符串,通常更有利于压缩;方案 B 则允许单独解压某个文件,但会损失跨文件压缩机会。
2. 基本创建、查看和提取
准备测试目录:
mkdir -p demo/etc demo/logs
printf 'server=example\n' > demo/etc/app.conf
printf 'same line\nsame line\n' > demo/logs/app.log
ln demo/etc/app.conf demo/etc/app.conf.hardlink
ln -s ../etc/app.conf demo/logs/app.conf.link
创建未压缩归档:
tar -cf demo.tar demo/
参数含义:
-c:create,创建归档;-f demo.tar:指定归档文件;demo/:要归档的路径。
查看归档目录,不释放文件:
tar -tf demo.tar
典型输出:
demo/
demo/etc/
demo/etc/app.conf
demo/etc/app.conf.hardlink
demo/logs/
demo/logs/app.log
demo/logs/app.conf.link
提取到当前目录:
mkdir restore
tar -xf demo.tar -C restore
这里的 -x 是 extract,-C restore 表示在提取前切换到 restore 目录。归档中的路径仍会保留 demo/ 前缀,因此结果是:
restore/demo/etc/app.conf
只提取某个路径:
tar -xf demo.tar -C restore demo/etc/app.conf
列出单个文件内容而不落盘:
tar -xOf demo.tar demo/etc/app.conf
-O 将文件内容写到标准输出,适合查看配置或把归档中的内容交给其他命令。不要对大型二进制文件随意使用,因为内容会直接写入终端或管道。
3. 归档根目录和路径名
下面两条命令保存的路径不同:
tar -cf absolute.tar /etc/hosts
tar -cf relative.tar -C /etc hosts
现代 GNU tar 通常会去除归档中的前导 /,并给出类似“Removing leading /'”的提示,以避免提取时默认覆盖绝对路径。第二条命令明确保存为 hosts`,通常更适合可移植归档。
更常用的写法是从目标目录的父目录开始:
tar -C /var -czf var-backup.tar.gz lib/systemd
这样归档中的路径是 lib/systemd/...,而不是 /var/lib/systemd/...。恢复时可以选择目标根目录:
tar -xzf var-backup.tar.gz -C /restore-root
三、gzip、xz 和 zstd 的区别
1. gzip:兼容性优先
gzip 使用 DEFLATE 压缩算法。它的特点是:
- 在 Unix 工具链中普及时间长;
- 几乎所有 Linux、BSD、macOS 和归档工具都支持;
- 压缩和解压通常较快;
- 压缩率一般不如 xz;
- 支持流式处理。
直接压缩 tar:
tar -czf demo.tar.gz demo/
其中 -z 表示通过 gzip 处理。
手动拆开两步:
tar -cf demo.tar demo/
gzip -k demo.tar
-k 保留原始 demo.tar。如果不使用 -k,gzip 默认可能删除未压缩的输入文件。
验证 gzip 数据流:
gzip -t demo.tar.gz
无输出且退出状态为 0,通常表示 gzip 数据流的校验通过。注意,这不等于已经验证 tar 中的每个文件都能按预期恢复;还应测试 tar 层:
tar -tzf demo.tar.gz > /dev/null
2. xz:压缩率优先
xz 通常使用 LZMA2。它的特点是:
- 对文本、源码、日志等数据通常有较好的压缩率;
- 高压缩级别可能需要较多 CPU 和内存;
- 解压通常比压缩轻,但仍可能受内存和字典大小影响;
- 适合发布包、长期存档和带宽受限场景;
- 不应仅因为压缩率高就用于所有在线备份。
创建 xz 归档:
tar -cJf demo.tar.xz demo/
-J 表示 xz。
显式测试:
xz -t demo.tar.xz
tar -tJf demo.tar.xz > /dev/null
设置压缩级别:
tar -cJf demo.tar.xz demo/
GNU tar 的 -J 使用 xz 默认设置。若需要显式传递参数,可以使用 -I:
tar -I 'xz -6' -cf demo.tar.xz demo/
压缩级别不是简单的“越大越好”。更高级别通常提高压缩时间和内存消耗,实际节省的空间可能很小。生产环境应使用真实数据测试,而不是根据数字直接推断收益。
3. zstd:速度和压缩率的平衡
zstd 是现代压缩格式,通常在压缩速度、解压速度和压缩率之间取得较好的平衡。它支持:
- 流式压缩;
- 多线程压缩;
- 不同压缩级别;
- 字典压缩;
- 对大型数据流的较好吞吐表现。
创建 zstd 归档:
tar --zstd -cf demo.tar.zst demo/
也可以使用显式压缩命令:
tar -I 'zstd -3' -cf demo.tar.zst demo/
使用多个线程:
tar -I 'zstd -T0 -3' -cf demo.tar.zst demo/
-T0 通常表示让 zstd 使用可用 CPU 线程数,但具体资源消耗由 zstd 版本、CPU 和输入决定。在线备份中盲目使用所有线程,可能影响同机业务。
验证:
zstd -t demo.tar.zst
tar --zstd -tf demo.tar.zst > /dev/null
4. 选择压缩器的因果关系
可以从数据流和资源约束推导选择:
| 场景 | 通常更合适的选择 | 原因 |
|---|---|---|
| 需要最大兼容性 | gzip | 工具链支持广 |
| 发布包、长期存储、带宽昂贵 | xz | 通常更重视压缩率 |
| 在线备份、快速传输、现代 Linux | zstd | 通常在速度和压缩率间平衡 |
| 已压缩媒体或 ZIP | 低级别 gzip/zstd,甚至不压缩 | 再压缩收益小,CPU 可能浪费 |
这些是经验取舍,不是格式规范保证。实际结果取决于输入数据、压缩级别、CPU、磁盘和网络。
四、归档中的元数据:权限、所有者、链接和扩展属性
1. 文件内容不等于文件状态
仅保存普通文件内容,无法完整恢复一个 Linux 系统中的文件状态。恢复结果还可能受到以下信息影响:
- 权限位,例如
0644、0755; - 用户和组;
- 符号链接;
- 硬链接关系;
- 文件时间;
- ACL;
- xattr,例如 SELinux 标签;
- 稀疏文件的空洞;
- 设备节点和 FIFO。
GNU tar 默认会保存许多基本属性,但 ACL 和 xattr 需要显式启用:
sudo tar --acls --xattrs -czf etc-backup.tar.gz /etc
恢复时也应使用对应选项:
sudo tar --acls --xattrs -xzf etc-backup.tar.gz -C /restore-root
这不是所有 tar 实现都完全一致。GNU tar 的选项不能无条件假设在 BusyBox tar、BSD tar 或其他精简环境中存在。跨发行版恢复前应检查:
tar --version
tar --help | grep -E 'acls|xattrs|sparse'
2. 所有者恢复需要权限
普通用户创建归档时,通常无法读取其他用户的文件,也无法在恢复时任意设置文件所有者。系统级备份一般需要 root 或具有相应能力的进程:
sudo tar --acls --xattrs -czf /backup/etc.tar.gz -C / etc
恢复时:
sudo tar --acls --xattrs -xzf /backup/etc.tar.gz -C /restore-root
即使以 root 恢复,也应区分两种目标:
- 系统恢复:希望尽可能保留原所有者、权限、设备节点和标签;
- 普通文件分发:希望文件归当前用户所有,避免归档中的 UID 造成访问问题。
如果目标是普通用户可读目录,直接使用系统恢复参数可能导致文件属于不存在的 UID,或属于 root 而当前用户无法修改。
3. 硬链接和符号链接
硬链接是同一个 inode 的多个目录项;符号链接是保存目标路径的特殊文件。tar 通常会记录硬链接关系,而不是重复写入硬链接指向的文件内容。
验证恢复后的硬链接:
stat -c '%d:%i %n' restore/demo/etc/app.conf \
restore/demo/etc/app.conf.hardlink
如果两者 inode 相同,说明硬链接关系保留。
符号链接应使用:
readlink restore/demo/logs/app.conf.link
归档和恢复时不要把符号链接误当作普通文件。处理不可信归档时,符号链接可能与目录覆盖组合形成安全风险,因此恢复权限和目标目录必须受控。
五、校验和:验证完整性,但不要误当作认证
1. SHA-256 校验文件是否发生变化
对归档文件计算 SHA-256:
sha256sum demo.tar.zst > demo.tar.zst.sha256
cat demo.tar.zst.sha256
输出类似:
<64 个十六进制字符> demo.tar.zst
在另一台机器或传输后验证:
sha256sum -c demo.tar.zst.sha256
成功时通常输出:
demo.tar.zst: OK
这里校验的是整个压缩归档文件。只要一个字节变化,摘要大概率就会变化。
2. 压缩器内部校验和与外部校验和不是一回事
gzip、xz、zstd 的格式通常包含各自的数据完整性检查。命令:
gzip -t file.tar.gz
xz -t file.tar.xz
zstd -t file.tar.zst
主要检查压缩格式内部的数据是否损坏。
外部 SHA-256 文件则解决另一个问题:传输后拿到的文件是否与发布者或备份端计算的文件一致。
完整验证可以分层进行:
sha256sum -c demo.tar.zst.sha256 &&
zstd -t demo.tar.zst &&
tar --zstd -tf demo.tar.zst > /dev/null
三步分别对应:
- 文件与记录中的摘要一致;
- zstd 压缩流可以正确解码;
- 解码后的 tar 结构可以读取。
如果还要验证实际恢复结果,必须真正提取到隔离目录并检查文件:
rm -rf restore-check
mkdir restore-check
tar --zstd -xf demo.tar.zst -C restore-check
diff -ruN demo restore-check/demo
对于包含特殊元数据的备份,还需要额外检查:
stat restore-check/demo/etc/app.conf
getfacl restore-check/demo/etc/app.conf 2>/dev/null
getfattr -d restore-check/demo/etc/app.conf 2>/dev/null
3. 校验和不提供身份认证
SHA-256 可以发现随机损坏,但如果攻击者能够同时修改归档和 .sha256 文件,就可以重新计算摘要。因此:
- 完整性检查:使用 SHA-256;
- 来源认证:使用数字签名或带密钥的 MAC;
- 保密性:使用加密工具或加密备份系统。
例如,签名流程可以是:
sha256sum demo.tar.zst > demo.tar.zst.sha256
gpg --detach-sign --armor demo.tar.zst.sha256
验证需要可信的公钥:
gpg --verify demo.tar.zst.sha256.asc demo.tar.zst.sha256
sha256sum -c demo.tar.zst.sha256
签名验证通过,只能说明摘要文件由对应私钥签名;随后仍需执行 SHA-256 校验,确认归档文件确实匹配该摘要。
六、一个可验证的备份流程
下面的示例将 demo/ 归档为 zstd 文件,并同时保留校验和。
set -euo pipefail
src="$(pwd)/demo"
out="$(pwd)/backup"
mkdir -p "$out"
tar --acls --xattrs \
--zstd \
-cf "$out/demo.tar.zst" \
-C "$(dirname "$src")" \
"$(basename "$src")"
sha256sum "$out/demo.tar.zst" > "$out/demo.tar.zst.sha256"
zstd -t "$out/demo.tar.zst"
tar --acls --xattrs --zstd -tf "$out/demo.tar.zst" > "$out/demo.file-list"
sha256sum -c "$out/demo.tar.zst.sha256"
每一步的作用不同:
tar ... -cf读取源目录并生成归档;-C使归档使用相对路径,避免直接保存/绝对路径;--acls --xattrs请求保存 ACL 和扩展属性;sha256sum记录归档文件的外部摘要;zstd -t验证压缩层;tar -t验证 tar 层能够遍历;sha256sum -c验证文件没有被改变。
set -o pipefail 对管道很重要。例如:
set -o pipefail
tar -cf - demo | zstd -3 > demo.tar.zst
如果 tar 因为权限错误提前失败,而 zstd 正常结束,缺少 pipefail 时脚本可能只看到 zstd 的成功状态。启用 pipefail 后,只要管道中的任意关键命令失败,管道状态就会反映失败。
生产脚本还应避免在归档未验证前删除源数据:
if tar --zstd -cf backup.tar.zst demo/ &&
zstd -t backup.tar.zst &&
sha256sum backup.tar.zst > backup.tar.zst.sha256
then
echo "归档已创建,尚未删除源数据"
else
echo "归档失败,保留源数据" >&2
exit 1
fi
“命令返回 0”只表示该命令认为操作成功,不表示备份策略已经具备可恢复性。恢复演练仍然必须定期执行。
七、大文件的核心问题
“大文件”不是单一限制,而是多个边界叠加:
- 文件系统是否支持该大小;
- tar 格式是否能表示该文件大小;
- 压缩器的字典、内存和时间是否可接受;
- 单个归档是否适合传输;
- 失败后是否能从中间位置恢复;
- 目标介质是否支持相同的稀疏文件、权限和元数据。
1. 现代 Linux 通常支持大于 4 GiB 的文件
在现代 64 位 Linux 和常见文件系统上,单个普通文件超过 4 GiB 通常没有问题。历史 tar 格式曾存在文件大小字段限制,因此现代 GNU tar 使用 POSIX pax 扩展或 GNU 扩展表示大文件。
可以检查归档格式:
tar --format=pax -cf large.tar large-file
pax 格式是 POSIX 体系中用于扩展 tar 元数据的格式,适合需要长文件名、大文件大小、扩展时间等信息的场景。若需要和非常老的 tar 工具互操作,必须在创建端和恢复端实际测试;“现代 Linux 可以创建”不代表“老系统一定能读取”。
2. 内存不一定与文件总大小相等
tar 处理文件时通常按块读取,并不需要把整个文件载入内存。压缩器的内存消耗主要受算法、压缩级别、字典大小和实现影响。
因此,一个 1 TiB 文件不必然要求 1 TiB 内存,但以下风险仍存在:
- xz 高级别可能消耗较多内存;
- zstd 大字典或高压缩级别会提高资源使用;
- 多线程压缩会同时增加 CPU 和内存压力;
- 磁盘、网络和目标文件系统可能先成为瓶颈。
可以先观察输入和输出,不要只凭文件名判断:
du -h --apparent-size large-file
du -h large-file
ls -lh large-file
--apparent-size 显示逻辑大小;普通 du 通常反映实际占用的磁盘块。两者差距很大时,文件可能是稀疏文件。
3. 稀疏文件
稀疏文件包含逻辑上的大段零,但这些零可能没有实际分配磁盘块。若普通复制或归档过程把空洞当作真实零字节写入,恢复后文件逻辑大小相同,但磁盘占用会显著增加。
创建一个稀疏文件:
truncate -s 10G sparse.img
du -h sparse.img
du -h --apparent-size sparse.img
使用 GNU tar 的稀疏选项:
tar --sparse -cf sparse.tar sparse.img
tar --sparse -xf sparse.tar -C restore
恢复后比较:
du -h restore/sparse.img
du -h --apparent-size restore/sparse.img
--sparse 通过识别零块并在归档中记录空洞来减少实际数据量。目标文件系统必须支持相应的稀疏文件语义,否则恢复结果可能仍占用实际零块。
4. 分卷和 split
压缩归档通常是一个连续数据流。如果文件太大,不适合直接放入某个文件系统、对象存储对象或移动介质,可以在压缩完成后切分:
split -b 4G --numeric-suffixes=1 --suffix-length=4 \
demo.tar.zst demo.tar.zst.part-
结果类似:
demo.tar.zst.part-0001
demo.tar.zst.part-0002
demo.tar.zst.part-0003
恢复为完整归档:
cat demo.tar.zst.part-* > demo-restored.tar.zst
这里使用固定宽度数字后缀,能够保证字典序与分片顺序一致。不要使用可能产生如下排序问题的命名:
part-1
part-2
part-10
因为普通字典序可能把 part-10 排在 part-2 前面。
应同时记录:
sha256sum demo.tar.zst.part-* > parts.sha256
sha256sum demo-restored.tar.zst > demo-restored.tar.zst.sha256
恢复时先验证分片,再拼接:
sha256sum -c parts.sha256
cat demo.tar.zst.part-* > demo-restored.tar.zst
sha256sum -c demo-restored.tar.zst.sha256
zstd -t demo-restored.tar.zst
分片不会增加随机恢复能力。若第 2 个分片损坏,连续压缩流可能从该位置开始无法继续解码,仍需要重新获得损坏分片或整个归档。
GNU tar 也有 -M 多卷归档功能,但它面向磁带等顺序介质,常涉及换卷提示和交互式流程:
tar -cMf archive.tar -L 4000000 source/
这种方式不一定适合无人值守的文件上传。对于普通文件、对象存储和脚本流程,先生成压缩归档再使用 split 通常更容易验证和重试。
5. 流式传输和远程归档
tar 不要求归档必须落在本地文件中,可以写到标准输出:
tar -cf - demo | zstd -3 | ssh backup-host 'cat > /backup/demo.tar.zst'
恢复时反向处理:
ssh backup-host 'cat /backup/demo.tar.zst' |
zstd -dc |
tar -xf - -C restore
这类命令的数据流是:
本地 tar
-> 本地 zstd
-> SSH 加密传输
-> 远端文件
SSH 已经提供传输加密,但没有自动替代文件级校验。传输后仍应在发送端和接收端分别计算摘要,或者在接收端验证已保存文件。
如果需要边传输边计算摘要,可以使用 tee:
set -o pipefail
tar -cf - demo |
zstd -3 |
tee demo.tar.zst |
sha256sum > demo.tar.zst.sha256
这里 tee 将同一数据流同时写入文件和 sha256sum。只有在整个管道成功结束后,摘要文件才应被视为有效。若磁盘写满、源文件读取失败或 SSH 断开,必须检查各命令退出状态,而不是仅查看输出文件是否存在。
八、归档一致性:正在变化的文件不能自动变成一致备份
tar 读取文件时,文件可能仍在被其他进程写入。可能出现以下状态:
- tar 先读取到文件大小;
- 应用继续追加内容;
- tar 读取到旧大小以内的一部分或全部内容;
- 归档记录的内容与某个瞬间的完整文件状态不一致。
即使 tar 成功退出,这也不代表数据库、虚拟机磁盘或多个相互关联文件处于一致状态。
普通日志文件
日志追加通常可以接受“某个时间窗口内的近似快照”,但要明确这不是严格一致备份。
数据库
数据库文件可能有页缓存、WAL、事务日志和多个关联文件。直接 tar 数据目录可能得到无法恢复或需要额外修复的状态。应使用数据库原生备份机制,或者先创建一致性快照,再从快照上归档。
LVM、文件系统和虚拟机快照
更可靠的流程通常是:
应用协调或暂停写入
│
▼
创建一致性快照
│
▼
从快照读取并 tar + 压缩
│
▼
校验、传输、恢复演练
快照只提供某个时刻的视图,并不自动提供长期备份。快照所在存储损坏、被误删或空间耗尽时,快照本身不能替代独立备份。
九、递归归档时的边界与排除
递归归档可能把不应保存的内容一起写入,例如:
/proc、/sys、/dev、/run等伪文件系统;- 挂载在源目录下的其他文件系统;
- 缓存、临时文件和构建产物;
- 备份输出目录本身,导致递归增长;
- 包含密码、令牌和私钥的配置文件。
对系统目录归档时,--one-file-system 可以避免跨越文件系统边界:
sudo tar --one-file-system \
--acls --xattrs \
--zstd -cf root-files.tar.zst -C / \
etc home var
--one-file-system 不是“只归档一个目录”的意思,而是当递归遍历遇到不同设备号的挂载点时不继续进入。它适合避免把 NFS、容器挂载或临时文件系统意外打包,但也可能漏掉业务真正需要的数据,因此必须明确备份范围。
排除路径:
tar --zstd -cf home.tar.zst \
--exclude='home/*/.cache' \
-C / home
排除模式的语义与 tar 版本有关,复杂规则应先用 tar -tvf 检查归档清单,不要直接依赖 shell 展开。
十、解压不可信归档的安全边界
tar 归档可以包含绝对路径、.. 路径、符号链接、设备节点和特殊文件。直接以 root 解压不可信归档,可能覆盖系统文件或制造符号链接相关风险。
先查看清单:
tar --zstd -tvf untrusted.tar.zst
检查可疑路径:
tar --zstd -tf untrusted.tar.zst |
grep -E '(^/|(^|/)\.\.(/|$))'
更安全的基本做法:
mkdir -p /tmp/safe-restore
tar --zstd \
--no-absolute-names \
--keep-old-files \
-xf untrusted.tar.zst \
-C /tmp/safe-restore
含义:
--no-absolute-names:不按归档中的绝对路径写入;--keep-old-files:目标文件已存在时不覆盖;- 使用专门的临时目录,避免直接写入生产目录。
--keep-old-files 会使已存在的文件导致提取失败,这通常是安全行为。若确实需要覆盖,应先确认归档来源、清理目标目录并明确恢复范围,而不是简单删除保护选项。
设备节点、所有者和权限恢复通常需要 root,因此最安全的做法是:
- 先以普通用户在隔离目录查看;
- 只提取需要的内容;
- 确认归档来源;
- 必须系统恢复时,再在受控环境中使用 root。
十一、可重复归档和时间变化
相同文件内容不一定产生相同 tar 文件,因为归档还包含:
- 修改时间;
- 所有者和组;
- 文件遍历顺序;
- tar 格式;
- pax 扩展字段;
- ACL 和 xattr;
- 压缩器版本或参数。
如果要构建可复现的软件发布包,可以显式固定部分字段:
tar --format=pax \
--sort=name \
--mtime='UTC 1970-01-01' \
--owner=0 \
--group=0 \
--numeric-owner \
-cf source.tar source/
各选项的目的:
--sort=name:固定文件遍历顺序;--mtime:固定修改时间;--owner=0 --group=0:固定归档中的数值所有者;--numeric-owner:不依赖创建机器上的用户名解析;--format=pax:使用现代扩展格式表示长名称和大文件。
但这不等于所有环境下的字节级可复现。xattr、ACL、文件名编码、pax 字段和压缩器版本仍可能产生差异。可复现构建必须把这些输入也纳入控制;普通备份则不应为了“文件字节完全相同”而擅自丢弃真实元数据。
十二、tar 增量选项不是完整备份策略
GNU tar 提供基于快照文件的增量能力,例如:
tar --listed-incremental=snapshot.snar \
-czf backup-inc.tar.gz data/
该机制会记录目录状态,后续运行时根据快照文件判断哪些文件变化。它与 rsync 的增量算法不同,也不是数据库级备份,更不是快照。
需要特别注意:
snapshot.snar是增量链状态的一部分;- 完整备份和后续增量必须保留正确顺序;
- 丢失或错误替换快照文件会破坏增量判断;
- 删除文件的表达和恢复行为需要实际测试;
- 增量链越长,恢复依赖越多;
- 并发修改期间仍然存在一致性问题。
如果目标是长期备份,通常需要设计完整备份、增量备份、保留周期、异地副本、校验和和恢复演练,而不是仅给 tar 增加一个增量参数。
十三、常见失败表现和诊断顺序
“tar: Cannot open: Permission denied”
原因通常是:
- 当前用户无权读取源文件;
- 无权写入目标目录;
- 目标归档已存在但无权覆盖;
- 父目录搜索权限不足。
诊断:
id
namei -l /path/to/source
ls -ld /path/to/output
必要时使用 sudo,但不要把 sudo 当作忽略权限设计的工具。备份脚本应明确运行身份和输出文件权限。
“Unexpected EOF” 或压缩测试失败
可能原因:
- 文件未传输完整;
- 分片缺失或顺序错误;
- 磁盘写满导致输出被截断;
- 网络连接中断;
- 文件在生成过程中被读取;
- 存储介质发生损坏。
诊断顺序:
sha256sum -c backup.tar.zst.sha256
zstd -t backup.tar.zst
tar --zstd -tf backup.tar.zst > /dev/null
df -h
df -i
先检查外部摘要,再检查压缩层和 tar 层,可以区分“文件变了”和“文件本身结构损坏”。
“tar: Removing leading /”
这通常是 tar 为避免提取到绝对路径而进行的安全处理提示,不一定是错误。更好的创建方式是使用:
tar -C / -cf root-part.tar etc
让归档从一开始就使用相对路径。
归档恢复后文件所有者不对
可能是:
- 创建时不是 root,无法读取原始所有者;
- 恢复时不是 root,无法设置所有者;
- 使用了用户名而非数值 UID/GID;
- 目标系统没有同名用户;
- 目标系统的 UID 分配不同。
系统恢复时使用数值 UID、root、ACL 和 xattr 选项,并在目标环境检查身份数据库。跨主机迁移普通数据时,则应根据目标系统的用户模型重新设置所有者。
十四、一个完整的恢复验证流程
假设已经拿到:
demo.tar.zst
demo.tar.zst.sha256
先在非生产目录执行:
set -euo pipefail
sha256sum -c demo.tar.zst.sha256
zstd -t demo.tar.zst
rm -rf restore-check
mkdir restore-check
tar --zstd -xf demo.tar.zst -C restore-check
随后检查目录内容:
find restore-check/demo -printf '%M %u:%g %s %p\n' | sort
检查内容差异:
diff -ruN demo restore-check/demo
检查硬链接:
stat -c '%i %n' \
restore-check/demo/etc/app.conf \
restore-check/demo/etc/app.conf.hardlink
检查符号链接:
readlink restore-check/demo/logs/app.conf.link
如果备份包含稀疏文件、ACL、xattr、设备节点或服务配置,还应分别验证这些属性。只有“归档可以列目录”而没有“实际提取并检查”,不能证明恢复流程可用。
结语
tar 解决的是文件集合、路径和元数据的顺序归档;gzip、xz 和 zstd 解决的是归档数据流的压缩;压缩器内部检查和外部 SHA-256 解决的是不同层面的损坏检测。大文件则把 tar 格式、文件系统、压缩资源、流式传输、分片和恢复顺序这些问题同时暴露出来。
可靠流程不是“执行一条 tar 命令”,而是:
确定一致的数据视图
-> 正确选择归档范围和元数据
-> 选择压缩器与资源参数
-> 生成归档
-> 计算外部校验和
-> 验证压缩层和 tar 层
-> 在隔离环境中实际恢复
-> 定期重复恢复演练
在生产环境中,备份文件只有在能够被验证、传输、读取并恢复为正确状态时,才真正具有备份价值。
系列导航与关联阅读
- 系列入口:Linux 完整学习路线:从内核与文件系统到网络、性能和生产运维
- 上一篇:tmux 终端复用:Session、窗口、Pane、恢复和远程运维边界
- 下一篇:rsync 文件同步:增量算法、权限、删除、断点和备份策略
- 延伸:Linux 备份与恢复:文件、块设备、快照、加密和恢复演练
官方资料
本文依据 Linux 内核、systemd 与主流发行版官方文档重新梳理;正文与实验由 WR BLOG 编写。

评论
0 条讨论