tar —— 打包、压缩与备份

运维工具手册 03-文件与传输 5.3 KB 原文

tar —— 打包、压缩与备份

分类:03 文件与传输 适用:全平台(GNU tar 1.3x / bsdtar) 一句话:Linux 备份与交付的通用容器,能保留权限、属主、软链接、SELinux 上下文。

1. 它解决什么问题

  • 把目录打成单文件交付/备份。
  • 保留权限、属主、时间戳、软链接(cp 容易丢)。
  • 与压缩工具组合(gzip/zstd/xz),与 SSH 组合做流式传输。
  • 增量备份(--listed-incremental)。

2. 先记住三种操作

操作 参数 记忆
创建 -c create
解开 -x extract
列出 -t list

再加压缩:-z gzip、-j bzip2、-J xz、--zstd zstd、--lz4。

顺序很重要:tar -czf 中 f 必须紧跟归档文件名,写成 tar -cfz 会把 z 当文件名。

3. 基础用法

# 创建
tar -czf backup.tar.gz /data                 # gzip,最常用
tar -cjf backup.tar.bz2 /data                # bzip2,压缩率高但慢
tar -cJf backup.tar.xz /data                 # xz,最高压缩比,最慢
tar --zstd -cf backup.tar.zst /data          # zstd,速度与压缩比均衡(推荐)
tar -cf backup.tar /data                     # 不压缩

# 查看(不解压)
tar -tzf backup.tar.gz | head
tar -tzf backup.tar.gz | grep 'nginx.conf'   # 找某个文件

# 解压
tar -xzf backup.tar.gz                       # 解到当前目录
tar -xzf backup.tar.gz -C /restore           # 解到指定目录
tar -xzf backup.tar.gz path/to/file           # 只解某个文件
tar -xzf backup.tar.gz --strip-components=1  # 去掉第一层目录

4. 关键参数

参数 作用 场景
-v 显示处理文件 交互使用;脚本里会拖慢
-p 保留权限 解压时以 root 运行默认保留
--numeric-owner 按数字保留属主 跨系统恢复必用
-C <dir> 切换目录 打包/解包指定位置
--exclude= 排除 可多次
--exclude-from= 从文件读排除
-h / --dereference 跟随软链接(存实体) 默认存软链本身
-P / --absolute-names 允许绝对路径 解压时危险,会覆盖原路径
--one-file-system 不跨文件系统 备份 / 时必备
--warning=no-file-changed 忽略"文件变化"警告 备份活动日志
--ignore-failed-read 读失败继续 有坏文件时
-S 处理稀疏文件 镜像/虚拟机磁盘
--totals 输出总字节
--checkpoint=.1000 每 1000 个文件打点 长任务看进度
-W / --verify 写完校验 磁带/重要备份
--remove-files 打包后删源 归档并清理

5. 流式与管道

# 打包直接传到远端(不落本地盘)
tar -czf - /data | ssh user@host 'tar -xzf - -C /backup'

# 边打包边算校验
tar -czf - /data | tee >(sha256sum > /tmp/sum.txt) | ssh host 'cat > /data.tar.gz'

# 从 stdin 解压
curl -sL https://example.com/pkg.tar.gz | tar -xzf - -C /opt

# 大目录跨机迁移加 pv 看进度
tar -cf - /data | pv | ssh host 'tar -xf - -C /backup'

# 拆包(超大文件分卷)
tar -czf - /data | split -b 2G - /backup/data.tar.gz.part_
cat /backup/data.tar.gz.part_* | tar -xzf - -C /restore

流式传输的好处是不占本地临时空间,坏处是中断要重来(用 rsync 更适合大体量)。

6. 排除规则

tar -czf backup.tar.gz \
  --exclude='*.log' \
  --exclude='./data/cache' \
  --exclude='./data/tmp' \
  -C / data

# 从文件读
cat > /tmp/exclude.txt <<'EOF'
data/cache
data/tmp
*.pid
EOF
tar -czf backup.tar.gz --exclude-from=/tmp/exclude.txt -C / data

要点:

  • 相对路径基于 -C 指定的目录。
  • *.log 会匹配任意层级的 log 文件。
  • 排除目录要写对名字,末尾不要加 /(GNU tar 对目录匹配较宽松,但保持一致更稳)。

7. 实战场景

7.1 备份前先排除伪文件系统

tar -czf /backup/root-$(date +%F).tar.gz \
  --one-file-system \
  --exclude=/proc --exclude=/sys --exclude=/dev --exclude=/run \
  --exclude=/tmp --exclude=/var/cache --exclude=/backup \
  --warning=no-file-changed \
  / 2>/dev/null

--one-file-system 已经能挡住大部分挂载点,但显式排除更保险。

7.2 保留 SELinux 上下文

GNU tar 1.28+ 默认会保存 security.selinux xattr。老版本用:

tar --selinux -czf backup.tar.gz /var/www
# 恢复后
restorecon -Rv /var/www

7.3 增量备份

# 第一次:全量,生成快照文件
tar -czf /backup/full-$(date +%F).tar.gz --listed-incremental=/backup/snap.file /data
# 之后:增量
tar -czf /backup/inc-$(date +%F).tar.gz --listed-incremental=/backup/snap.file /data
# 恢复必须按顺序:full → inc1 → inc2 ...

tar 增量基于 mtime,改名/权限变化不一定被捕获;要求严格就用 rsync --link-dest 或 restic。

7.4 只解压部分文件

tar -tzf app.tar.gz | grep 'conf/'
tar -xzf app.tar.gz -C /tmp app/config/app.yml

7.5 恢复时去掉多余前缀

# 包里是 package-1.2.3/ 结构,想直接解到当前目录
tar -xzf pkg.tar.gz --strip-components=1 -C /opt/app

8. 常见坑

  1. -f 位置:tar -czf file.tar.gz dir 正确;tar -cz file.tar.gz dir 会当成无 f 报错或行为异常。
  2. 打包时路径带 / 开头:解压会覆盖原路径,务必用 -C / + 相对路径,或 --absolute-names 明确知道在干什么。
  3. 通配符被 shell 展开:tar -czf a.tar.gz *.log 在文件过多时会报 Argument list too long,用 --files-from 或 find -print0。
  4. 不保留属主:普通用户解压别人的包,属主变成自己;需要 --numeric-owner + root。
  5. 软链接被展开:默认存链接本身,若想存实体用 -h(可能造成循环)。
  6. 打包正在写的文件:得到不一致内容,加 --warning=no-file-changed 只是静音,不是解决。
  7. 解压覆盖无提示:GNU tar 默认直接覆盖,恢复前先 -t 看清楚。
  8. Alpine 用 bsdtar:--listed-incremental、--selinux 等 GNU 专有参数不支持,装 tar 包或改用 busybox tar 的有限功能。
  9. 压缩级别:gzip -1 到 -9 差别有限;大数据量优先 zstd -3,速度是 gzip 的数倍。
  10. -z 与 --zstd 不要同时用,会嵌套压缩。
  11. 解压到只读文件系统/空间不足:先 df -h 确认空间是包大小的 1.5~2 倍。

9. 压缩工具怎么选

工具 命令后缀 速度 压缩比 适用
gzip .tar.gz 中 中 通用兼容
bzip2 .tar.bz2 慢 较高 已过时,少用
xz .tar.xz 很慢 最高 长期归档、发行包
zstd .tar.zst 快 高 推荐,可调级别
lz4 .tar.lz4 极快 低 临时传输
tar -I 'zstd -T0 -3' -cf backup.tar.zst /data    # 多线程 zstd
zstd -d backup.tar.zst -o backup.tar

10. 速查表

tar -czf a.tar.gz dir/            # 打包 gzip
tar -cJf a.tar.xz dir/            # 打包 xz
tar --zstd -cf a.tar.zst dir/     # 打包 zstd
tar -tzf a.tar.gz                 # 列出
tar -xzf a.tar.gz -C /dest        # 解压到目录
tar -xzf a.tar.gz --strip-components=1
tar -xzf a.tar.gz path/in/archive # 解单个文件
tar -czf a.tar.gz --exclude='*.log' dir/
tar -czf - dir/ | ssh host 'tar -xzf - -C /dest'
tar -czf a.tar.gz --one-file-system --exclude=/proc /
tar -czf b.tar.gz --listed-incremental=snap /data
tar -czf a.tar.gz --numeric-owner -C / data
tar —— 打包、压缩与备份 - 知识库 - 起航社区