Skip to content

压缩与打包 ​

记住三件事: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)

参数含义:

参数作用
-ccreate,打包
-xextract,解包
-tlist,列表
-z / -j / -Jgzip / 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/restore
text
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 logs
text
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 | head
text
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 OK
text
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.gzzip
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-01

split 后必须校验合并结果:

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
tmp
bash
tar -czf app.tar.gz -C /opt/app --exclude-from=/tmp/exclude.txt .

排除规则写错很常见

--exclude='logs' 只排除名字正好叫 logs 的项;--exclude='*/logs/*' 排除任意层级的 logs 内容。拿不准时先 tar -tzf 检查一遍产物。

八、打包前先想三件事 ​

  1. 包里要不要顶层目录? 只有一个项目目录时带上它,解压不会把当前目录搞乱。
  2. 有没有正在写入的文件? 日志、数据库文件打包会得到不一致的快照。
  3. 产物放哪? 不要放在被别名的目录里,否则下次打包会把自己套进去。
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 用 GBKunzip -O GBK
压缩包打不开传输截断gzip -t / tar -tzf > /dev/null
打包把备份文件也包进去了产物放在了源目录产物放另一个路径
打包时文件被改有进程在写停写或用快照(LVM/云盘快照)
xz 压缩跑了几小时算法特性换 zstd,或调 -T0 多线程