登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  linux

tar 增量归档排除缓存目录的参数组合

来源:17golang原创

时间:2026-10-01 21:43:04 324浏览 收藏

要让 GNU tar 做增量归档并排除缓存目录,最稳妥的组合是:用 --listed-incremental=状态文件 持久记录变化,用 --exclude-from=规则文件 排除按名称确定的缓存路径,再用 --exclude-caches-all 补充排除带有效 CACHEDIR.TAG 的缓存目录。状态文件和归档文件都应放在源目录之外。

第一次使用一个不存在的快照文件时会形成完整基线;以后复用同一个快照文件,tar 会更新其中的文件系统状态并生成后续增量。排除规则也要在同一条归档链中保持稳定,否则应开启新的 level-0 基线。

官方地址:https://www.gnu.org/software/tar/manual/html_node/Incremental-Dumps.html

最小配方
  • -g app.snar 保存增量状态,不能把它当作可丢弃的临时文件。
  • -X app.exclude 读取一行一个的排除模式,适合维护多条缓存路径。
  • --exclude-caches-all 只识别带有效 CACHEDIR.TAG 的目录,不按目录名称猜测。

先用最小参数组合完成一次归档

下面的命令固定源目录为 /srv/app,把成员名保存为相对路径,同时把归档与 .snar 状态文件放到源目录之外。--one-file-system 是可选保护项,用于避免递归跨入挂载在源树下的其他文件系统。

#!/usr/bin/env bash
set -eu

SOURCE='/srv/app'
ARCHIVE_DIR='/srv/backup'
STATE_DIR='/var/lib/tar-snapshots'
EXCLUDES='/etc/backup/app.exclude'

# 快照文件必须跨轮次保留;归档名则要保证每次唯一。
SNAPSHOT="$STATE_DIR/app.snar"
ARCHIVE="$ARCHIVE_DIR/app-$(date +%F-%H%M%S).tar.gz"

mkdir -p "$ARCHIVE_DIR" "$STATE_DIR"

tar --create --gzip \
  --file="$ARCHIVE" \
  --listed-incremental="$SNAPSHOT" \
  --exclude-from="$EXCLUDES" \
  --exclude-caches-all \
  --one-file-system \
  --directory="$SOURCE" . # 以源目录为归档根,避免写入绝对路径。

--listed-incremental 的参数是 tar 的快照状态文件,不是输出归档。官方文档说明,它用于判断自上次备份以来新增、修改或删除的文件;执行创建操作后,该文件会被更新。不要把它放进待归档目录,也不要让清理脚本删除它。

GNU tar 增量归档的源目录、排除规则、快照文件与归档文件静态参数关系图
图1:参数组合说明图;输入边界、状态边界和输出边界以静态关系呈现,不表示实际执行顺序。

把名称规则放进独立排除文件

规则少时可以重复写多个 --exclude='模式';规则多时用 --exclude-from 更清楚。GNU tar 的排除项使用 shell glob,不是正则表达式。写在命令行的通配符必须加引号,避免先被 shell 展开;写在文件中则一行一个模式,以 # 开头的行可以作为注释。

# 排除归档根目录下的缓存目录。
./.cache
./tmp/cache

# 排除任意子目录中的同名缓存目录。
*/.cache
*/tmp/cache

# 这些目录可由依赖安装或构建过程重新生成。
*/node_modules/.cache
*/var/cache

是否要写得更宽取决于数据语义。不要仅因为目录名包含 cache 就使用 *cache*,它可能误排业务目录或文件。优先列出已经确认可重建的目录;排除一个目录节点时,其下内容也不会进入归档。

区分名称排除与缓存标签排除

--exclude-caches-all 并不是“排除所有名字叫 cache 的目录”。它查找的是有效的 CACHEDIR.TAG 文件。GNU tar 提供三种标签语义:--exclude-caches 保留目录节点和标签文件;--exclude-caches-under 只保留目录节点;--exclude-caches-all 连该目录节点也不归档。

需求参数归档结果
排除确定名称的 .cache--exclude 或 --exclude-from匹配目录及内容不进入归档
保留标签,排除标签目录内容--exclude-caches保留目录节点与 CACHEDIR.TAG
只保留标签目录节点--exclude-caches-under不保留标签文件和内容
整个标签目录都省略--exclude-caches-all目录节点也不进入归档

名称规则和标签规则可以同时使用:前者覆盖团队明确知道的缓存路径,后者尊重应用写入的标准缓存标签。这样不会把“目录名字”和“目录内容可重建”混为一谈。

名称模式、排除文件、CACHEDIR.TAG 与三种缓存排除参数的静态语义关系图
图2:缓存排除语义说明图;名称匹配和标签识别是两条独立判断边界,最终共同约束归档成员。

固定快照文件与归档根路径

一条增量链必须能找到同一个快照状态。首次运行若状态文件不存在,GNU tar 会创建它并形成基线;后续运行复用它,状态会继续推进。要强制开启新的完整基线,可以使用一个新的快照文件,或在 --listed-incremental 同时使用 --level=0。

# 排除策略或源目录边界变化时,开始新的 level-0 归档链。
tar --create --gzip \
  --file='/srv/backup/app-full.tar.gz' \
  --listed-incremental='/var/lib/tar-snapshots/app.snar' \
  --level=0 \
  --exclude-from='/etc/backup/app.exclude' \
  --exclude-caches-all \
  --directory='/srv/app' .

-C/--directory 也应固定。今天从 /srv 归档 app,明天却从 /srv/app 归档 .,成员名称边界会改变,不利于理解和恢复。把源根、排除文件、状态文件命名和归档链编号一起纳入备份配置。

检查成员并按顺序恢复

创建后先列出归档。对增量归档,GNU tar 可以在列表模式下结合 --incremental 和两次 --verbose 展示目录元数据;普通成员列表则适合快速搜索是否仍有 .cache 路径。

# 查看增量归档中的目录状态与成员信息。
tar --list --incremental --verbose --verbose \
  --file='/srv/backup/app-2026-10-01-210000.tar.gz'

# 快速检查成员名;有匹配项时需要回看排除模式。
tar --list --file='/srv/backup/app-2026-10-01-210000.tar.gz' \
  | grep -E '(^|/)\.cache(/|$)' || true

恢复时必须从完整基线开始,再按生成顺序应用每个增量归档。官方文档提醒,增量恢复会尝试还原创建归档时的精确目录状态,可能删除当时已不存在的文件。因此先恢复到空的暂存目录,不要把第一次演练直接指向生产目录。

# 使用空目录演练;依次应用完整归档和后续增量归档。
mkdir -p '/srv/restore-test'
tar --extract --listed-incremental=/dev/null \
  --file='/srv/backup/app-full.tar.gz' --directory='/srv/restore-test'
tar --extract --listed-incremental=/dev/null \
  --file='/srv/backup/app-inc-01.tar.gz' --directory='/srv/restore-test'

完整参数速查

参数作用常见错误
--listed-incremental=FILE读取并更新增量快照状态每次换一个文件,导致每次都像新基线
--exclude=PATTERN排除单个命令行模式没有引号,通配符被 shell 提前展开
--exclude-from=FILE从文件读取多条模式把 FILE 本身误当成要排除的路径
--exclude-caches-all省略带有效缓存标签的整个目录误以为会按 cache 目录名自动识别
--directory=DIR切换归档根目录不同轮次改变根路径与成员名称
--level=0强制建立新的完整基线在日常增量轮次误用,增加归档体积

常见问题

只写 --exclude-caches-all 就能排除 .cache 吗?

不能保证。只有目录中存在有效 CACHEDIR.TAG 时才会触发标签排除;确定名称的目录仍应放入 --exclude 或 --exclude-from 规则。

可以删除 .snar 后继续做增量吗?

删除后会失去前一轮状态,下一次将重新形成完整基线。快照文件应与归档链一起管理,但不等同于归档数据本身。

修改排除文件后能直接沿用旧链吗?

命令可以运行,但恢复语义会更难判断。运维上更稳妥的做法是把排除策略版本化,并在策略边界变化时开启新的 level-0 链。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>