用 tar 做出备份集
目标
使用 tar 创建 full backup 和 incremental backup,并掌握排除规则、权限保留和文件分割。
为什么重要
tar 的一个选项就可能改变恢复结果。若不使用 -C 而把绝对路径收入 archive,就无法选择恢复位置;不用 --numeric-owner 恢复,在不同系统中 owner 可能被错误映射;不用 --selinux 恢复,在 SELinux 系统中服务甚至可能无法启动。另外,--listed-incremental 的snapshot 文件保存着 incremental chain 的状态,因此必须一并保管——一旦丢失,下一次 incremental backup 实际上就会变成 full backup。
步骤
- 在
/root/bk/src下创建以下文件:app/main.py、app/conf.yaml、data/records.csv、logs/app.log、logs/old.log。每个文件至少写入一行,但只有data/records.csv必须填充到 200KB 以上。第 7 步会把 archive 按 64KB 分割;如果只有单行小文件,压缩结果甚至不到 1KB,只会生成一个分片。使用base64 /dev/urandom | head -c 240000 > data/records.csv之类的命令即可。 - 创建 full backup
/root/bk/full.tar.gz。archive 内路径必须以src/开头(禁止绝对路径)。 - 将 archive 的 entry 数量作为单独一行数字写入
/root/bk/count.txt。 - 创建 incremental backup。snapshot 文件为
/root/bk/snap.snar。先创建/root/bk/inc0.tar.gz,再添加src/app/new.py文件,然后创建/root/bk/inc1.tar.gz。inc1的 entry 数量必须少于inc0。 - 创建排除
logs/的 backup/root/bk/nolog.tar.gz。列表中不得出现logs。 - 把
/root/bk/src/app/conf.yaml的权限改为640,重新创建 full backup(/root/bk/perm.tar.gz),并在保留权限的情况下恢复到/root/bk/restore-perm/。将恢复文件的权限作为单独一行数字写入/root/bk/perm.txt,必须为640。 - 将
/root/bk/full.tar.gz按 64KB 分割,以/root/bk/split/full.part为前缀保存,再重新合并为/root/bk/rejoined.tar.gz。它与原文件的 sha256 必须相同。 - 创建包含以下 5 行的
/root/bk/report.txt:FULL_ENTRIES=<3번 값>/INC0_ENTRIES=<inc0 항목 수>/INC1_ENTRIES=<inc1 항목 수>/NOLOG_HAS_LOGS=no/REJOIN_OK=yes
参考
- 使用
tar -czf /root/bk/full.tar.gz -C /root/bk src创建时,archive 内路径会成为src/...。 - entry 数量可用
tar -tzf <파일> | wc -l统计。 - incremental backup 使用
tar --listed-incremental=/root/bk/snap.snar -czf <출력> -C /root/bk src。 - 分割使用
split -b 64K <파일> /root/bk/split/full.part,重新合并使用cat /root/bk/split/full.part* > <출력>。 - 常见错误 1:第 4 步每次都删除 snapshot 文件,导致每次都成为 full backup。
- 常见错误 2:第 6 步恢复时漏掉权限保留选项,umask 会生效并改变权限值。
创建 backup source
在 /root/bk/src 下创建以下文件:app/main.py、app/conf.yaml、data/records.csv、logs/app.log、logs/old.log。每个文件至少写入一行,但只有 data/records.csv 必须填充到 200KB 以上。第 7 步会把 archive 按 64KB 分割;如果只有单行小文件,压缩结果甚至不到 1KB,只会生成一个分片。使用 base64 /dev/urandom | head -c 240000 > data/records.csv 之类的命令即可。
混合放置子目录和日志,后续步骤的排除规则才有实际意义。
创建 full backup
创建 full backup /root/bk/full.tar.gz。archive 内路径必须以 src/ 开头(禁止绝对路径)。
有一个选项可以避免把绝对路径写入 archive,这样才能自由选择恢复位置。
检查 archive 列表
将 archive 的 entry 数量作为单独一行数字写入 /root/bk/count.txt。
有一个选项可以只查看内容而不解压。统计 entry 数量并写入文件。
创建两次 incremental backup
创建 incremental backup。snapshot 文件为 /root/bk/snap.snar。先创建 /root/bk/inc0.tar.gz,再添加 src/app/new.py 文件,然后创建 /root/bk/inc1.tar.gz。inc1 的 entry 数量必须少于 inc0。
snapshot 文件保存状态。持续使用同一个 snapshot 文件,incremental chain 才会延续。
应用排除规则
创建排除 logs/ 的 backup /root/bk/nolog.tar.gz。列表中不得出现 logs。
排除 pattern 可以指定多次,也可以从文件读取。结果列表中不得出现对应 entry。
确认权限保留
把 /root/bk/src/app/conf.yaml 的权限改为 640,重新创建 full backup(/root/bk/perm.tar.gz),并在保留权限的情况下恢复到 /root/bk/restore-perm/。将恢复文件的权限作为单独一行数字写入 /root/bk/perm.txt,必须为 640。
恢复时有选项可以准确还原权限和 owner。恢复后使用 stat 比较。
分割并重新合并 archive
将 /root/bk/full.tar.gz 按 64KB 分割,以 /root/bk/split/full.part 为前缀保存,再重新合并为 /root/bk/rejoined.tar.gz。它与原文件的 sha256 必须相同。
split 接收前缀并生成分片文件,重新合并使用 cat。
汇总 backup set
创建包含以下 5 行的 /root/bk/report.txt:
FULL_ENTRIES=<3번 값> / INC0_ENTRIES=<inc0 항목 수> / INC1_ENTRIES=<inc1 항목 수> / NOLOG_HAS_LOGS=no / REJOIN_OK=yes
汇总每个 archive 的大小和 entry 数量,值必须来自实际测量。