外观
压缩与打包
记住三件事:tar 的参数顺序、-C 切换目录、以及打包时别用绝对路径。
一、tar 的六个组合
bash
tar -czf app-2026-10-27.tar.gz /opt/app # 打包 + gzip
tar -tzf app-2026-10-27.tar.gz | head # 只看内容
tar -xzf app-2026-10-27.tar.gz -C /data/restore # 解到指定目录
tar -cjf app.tar.bz2 dir/ # bzip2(慢,压得比 gzip 小)
tar -cJf app.tar.xz dir/ # xz(最慢,最小)
tar --zstd -cf app.tar.zst dir/ # zstd(最快,压缩比接近 xz)参数含义:
| 参数 | 作用 |
|---|---|
-c | create,打包 |
-x | extract,解包 |
-t | list,列表 |
-z / -j / -J | gzip / bzip2 / xz |
-f | 指定文件名(必须紧跟文件名) |
-v | 显示过程 |
-C | 切换到指定目录再操作 |
-p | 保留权限 |
--exclude | 排除 |
bash
tar -czf logs.tar.gz -C /var/log --exclude='*.gz' nginx这条命令的含义:切到 /var/log,打包 nginx 目录下的内容(不包含 *.gz),产物放在当前目录。包里没有 /var/log 这几层路径,解压后直接就是 nginx/。
bash
tar -xzf logs.tar.gz -C /data/restore
ls /data/restoretext
nginx不要打包绝对路径
bash
tar -czf app.tar.gz /opt/app # 包里带 /opt/app解压到别处时会覆盖到 /opt/app,或者需要 --strip-components=2:
bash
tar -xzf app.tar.gz --strip-components=2 -C /data/newapp正确做法是 -C /opt app(相对路径)。
二、压缩率与速度
测试一份 1.2GB 的日志目录:
bash
time tar -czf /tmp/t-gzip.tar.gz -C /data logs
time tar --zstd -cf /tmp/t-zstd.tar.zst -C /data logs
time tar -cJf /tmp/t-xz.tar.xz -C /data logstext
gzip: real 1m12s size 218MB
zstd: real 0m19s size 196MB
xz: real 4m38s size 151MB| 算法 | 速度 | 压缩比 | 适用 |
|---|---|---|---|
| gzip | 中 | 中 | 通用,兼容性最好 |
| zstd | 最快 | 好 | 现代系统首选 |
| xz | 最慢 | 最好 | 归档长期保存 |
| bzip2 | 慢 | 好 | 基本被 zstd 取代 |
zstd 需要装 zstd 包(CentOS/Rocky 默认可能有,Ubuntu 需 apt install zstd)。
三、不解压查看内容
bash
tar -tzf app.tar.gz | head -20
gzip -dc app.log.gz | head
zcat app.log.gz | grep ERROR | head
zless app.log.gz
xzcat app.tar.xz | tar -tv | headtext
opt/app/app.jar
opt/app/config/application.yml
opt/app/logs/app.log验证压缩包完整性(下载/传输后必做):
bash
gzip -t app.tar.gz && echo OK
tar -tzf app.tar.gz > /dev/null && echo OK
xz -t app.tar.xz && echo OKtext
OK四、zip / unzip
bash
zip -r site.zip /var/www/html
unzip -l site.zip
unzip site.zip -d /data/www
unzip -O GBK site.zip # Windows 中文文件名乱码时text
Length Date Time Name
--------- ---------- ----- ----
1280 10-27-2026 21:00 var/www/html/index.html
--------- -------
1280 1 file与 tar 的取舍:
| tar.gz | zip | |
|---|---|---|
| Linux 权限 | 保留 | 部分保留 |
| 软链 | 保留 | 不保留 |
| Windows 兼容 | 需工具 | 原生 |
| 单文件解压 | 需要全部扫描 | 支持随机访问(更快) |
Linux 内部归档用 tar,跨平台交付用 zip。
五、分卷与合并
bash
# 大文件切成 1GB 一块
split -b 1G -d app.tar.gz app.tar.gz.part-
# 合并
cat app.tar.gz.part-* > app.tar.gz
# tar 自带分卷(适合磁带/多张盘)
tar -czf - -C /data bigdir | split -b 1G -d - bigdir.tar.gz.part-bash
ls -lh app.tar.gz.part-*text
-rw-r--r-- 1 root root 1.0G Oct 27 21:45 app.tar.gz.part-00
-rw-r--r-- 1 root root 386M Oct 27 21:45 app.tar.gz.part-01split 后必须校验合并结果:
bash
cat app.tar.gz.part-* | tar -tzf - > /dev/null && echo OK六、保留权限与属主
bash
# 备份系统文件(必须用 root)
tar -cpzf etc-backup.tar.gz /etc
tar -xpzf etc-backup.tar.gz -C /-p保留权限。- 解包时用 root 才能恢复属主;普通用户解包会变成自己。
--same-owner是默认行为(root 下),普通用户会忽略。
ACL 与扩展属性:
bash
tar --acls --xattrs -czf data.tar.gz /data/app
tar --acls --xattrs -xzf data.tar.gz -C /七、排除与筛选
bash
tar -czf app.tar.gz -C /opt/app \
--exclude='logs/*' \
--exclude='*.log' \
--exclude='.git' \
--exclude='tmp' \
.排除项相对于 -C 后的路径。--exclude-from=file 可以从文件读:
text
# /tmp/exclude.txt
logs/*
*.log
.git
node_modules
tmpbash
tar -czf app.tar.gz -C /opt/app --exclude-from=/tmp/exclude.txt .排除规则写错很常见
--exclude='logs' 只排除名字正好叫 logs 的项;--exclude='*/logs/*' 排除任意层级的 logs 内容。拿不准时先 tar -tzf 检查一遍产物。
八、打包前先想三件事
- 包里要不要顶层目录? 只有一个项目目录时带上它,解压不会把当前目录搞乱。
- 有没有正在写入的文件? 日志、数据库文件打包会得到不一致的快照。
- 产物放哪? 不要放在被别名的目录里,否则下次打包会把自己套进去。
bash
# 标准做法
cd /opt
tar -czf /data/backup/app-$(date +%F).tar.gz \
--exclude='app/logs/*' --exclude='app/tmp/*' app九、踩过的坑
| 现象 | 根因 | 处置 |
|---|---|---|
tar: Cowardly refusing to create an empty archive | 忘了 -f 或没给文件 | 检查参数 |
解压后多了一层 /opt/app | 打包时用了绝对路径 | -C + 相对路径,或 --strip-components |
| 解压后权限/属主不对 | 没用 -p 或非 root 解包 | root 解包 + -p |
| 中文文件名乱码 | zip 用 GBK | unzip -O GBK |
| 压缩包打不开 | 传输截断 | gzip -t / tar -tzf > /dev/null |
| 打包把备份文件也包进去了 | 产物放在了源目录 | 产物放另一个路径 |
| 打包时文件被改 | 有进程在写 | 停写或用快照(LVM/云盘快照) |
| xz 压缩跑了几小时 | 算法特性 | 换 zstd,或调 -T0 多线程 |