Linux: 压缩与归档——tar / gzip / zip 与数据备份

数据备份是运维的生命线。在 Linux 上,tar + gzip 是最通用的归档方案,rsync 是最强大的增量同步工具。

📋 前置知识:需要先掌握以下内容

1. 你将学到


2. 一个 "忘加排除参数" 的故事

(1) 痛点:打包了不该打包的东西

小明需要把项目文件夹发给同事——团队约定不传输 node_modules.git 目录,因为它们体积太大且不必要。

(2) 一条命令完美打包

BASH
tar -czf project.tar.gz \
    --exclude=node_modules \
    --exclude=.git \
    --exclude=__pycache__ \
    project/

(3) 收益:干净的包

小明的压缩包从 500MB(含 node_modules)降到了 2MB,同事解压后直接就能用。


3. 知识点讲解

(1) tar——打包工具

BASH
# 创建 tar 包
tar -cf archive.tar file1 file2 dir/    # 打包
tar -czf archive.tar.gz dir/            # 打包 + gzip 压缩

> 💡 **提示**:`tar -czf` 的选项助记——`c`(create 创建)、`z`(gzip 压缩)、`f`(file 指定文件名)。这是最常用的组合,生成的 `.tar.gz` 文件是 Linux 世界的标准分发格式。解压只需将 `c` 换成 `x`(extract):`tar -xzf`。
tar -cjf archive.tar.bz2 dir/           # 打包 + bzip2 压缩
tar -cJf archive.tar.xz dir/            # 打包 + xz 压缩

# 解包
tar -xf archive.tar                     # 解包(自动识别格式)
tar -xzf archive.tar.gz                 # 解压 .tar.gz
tar -xf archive.tar -C /target/dir/     # 解压到指定目录

# 查看内容
tar -tf archive.tar.gz                  # 预览包内文件列表

> ⚠️ **注意**:解压 tar 包前,先用 `tar -tf` 预览包内文件列表——确认没有"炸弹文件"(如解压出大量小文件或路径以 `/` 开头的绝对路径文件),避免覆盖系统文件或填满磁盘。

# 排除
tar -czf backup.tar.gz --exclude="*.log" --exclude=node_modules dir/
tar 选项 含义
-c 创建归档
-x 解包
-t 列出内容
-f 指定归档文件名
-z 通过 gzip 过滤
-j 通过 bzip2 过滤
-J 通过 xz 过滤
-v 显示处理的文件
-C 解压到指定目录
--exclude 排除匹配模式的文件

(2) 压缩算法对比

算法 扩展名 选项 压缩比 速度 适用场景
gzip .gz -z 日常备份和分发
bzip2 .bz2 -j 需要更高压缩比
xz .xz -J 最高 最慢 长期归档,最小体积

(3) zip/unzip——跨平台压缩

TEXT 📖 仅展示
# 压缩
zip -r project.zip project/             # 递归压缩目录
zip -r project.zip project/ -x "*.git*" # 排除 .git
zip -r project.zip project/ -P password # 加密

# 解压
unzip project.zip                       # 解压到当前目录
unzip project.zip -d /target/dir/       # 解压到指定目录
unzip -l project.zip                    # 查看内容不解压

# zip 的优势:所有操作系统原生支持

(4) rsync——增量同步

BASH
# 基本用法
rsync -av source/ destination/          # 本地同步(递归 + 保留属性)
rsync -av --delete source/ dest/        # 同步并删除 dest 中源没有的文件

> ℹ️ **说明**:`rsync --delete` 会让目标端与源端完全一致——删除目标端有但源端没有的文件。如果误操作(如源路径写错),可能导致目标端数据大量丢失。建议先加 `--dry-run` 预览操作,确认无误后再实际执行。
rsync -avz source/ user@host:/dest/     # 远程同步(压缩传输)
rsync -avz -e "ssh -p 2222" source/ host:/dest/  # 指定 SSH 端口

# 排除
rsync -av --exclude="node_modules" --exclude=".git" src/ dst/

# 增量备份(硬链接)
rsync -av --link-dest=../backup-yesterday/ src/ backup-today/

rsync 的优势:

▶ 示例:tar 打包和解包

TEXT 📖 仅展示
# 打包家目录下的 projects
tar -czf projects-backup.tar.gz ~/projects/

# 查看包内容
tar -tf projects-backup.tar.gz | head -10

# 解压到 /tmp
tar -xzf projects-backup.tar.gz -C /tmp/

# 带详细的输出
tar -czvf my-backup.tar.gz --exclude="*.log" /var/log/

▶ 示例:不同压缩算法对比

BASH
# 准备测试
mkdir -p /tmp/compress-test
cp -r /usr/share/doc/* /tmp/compress-test/ 2>/dev/null

# gzip
time tar -czf test.tar.gz -C /tmp compress-test
ls -lh test.tar.gz

# bzip2
time tar -cjf test.tar.bz2 -C /tmp compress-test
ls -lh test.tar.bz2

# xz
time tar -cJf test.tar.xz -C /tmp compress-test
ls -lh test.tar.xz

# 对比结果
# 通常:test.tar.gz 最大但最快,test.tar.xz 最小但最慢

输出:

TEXT 📖 仅展示
-rw-r--r-- 1 alice alice 1.2M test.tar.gz

real    0m0.234s
user    0m0.198s
sys     0m0.036s
-rw-r--r-- 1 alice alice 856K test.tar.bz2

real    0m1.456s
user    0m1.389s
sys     0m0.067s
-rw-r--r-- 1 alice alice 612K test.tar.xz

real    0m5.123s
user    0m4.987s
sys     0m0.136s

▶ 示例:zip 跨平台分发

TEXT 📖 仅展示
# 打包项目(排除不需要的目录)
cd ~/projects
zip -r myapp.zip myapp/ -x "myapp/node_modules/*" "myapp/.git/*" "myapp/__pycache__/*"

# 查看内容
unzip -l myapp.zip | head -20

# 加密打包
zip -r -e secret.zip confidential/    # 会提示输入密码

▶ 示例:rsync 备份

BASH
# 本地备份
rsync -av --delete ~/projects/ /backup/projects/

# 远程备份到服务器
rsync -avz -e "ssh -i ~/.ssh/mykey" \
    --exclude="node_modules" \
    --progress \
    ~/projects/ user@backup-server:/backups/

# 增量备份(用硬链接)
# 第一天
rsync -av /data/ /backup/2026-07-07/

# 第二天(只存变化的部分)
rsync -av --link-dest=/backup/2026-07-07/ /data/ /backup/2026-07-08/

输出:

TEXT 📖 仅展示
sending incremental file list
sent 1,234 bytes  received 512 bytes  2,492.00 bytes/sec
total size is 5.6M  speedup is 3,210.45

sending incremental file list
app.js
config.yaml
sent 4,567 bytes  received 128 bytes  9,390.00 bytes/sec
total size is 5.6M  speedup is 1,197.23

▶ 示例:自动备份脚本

BASH
#!/bin/bash
# auto-backup.sh - 自动备份关键目录

BACKUP_ROOT="/backup"
DATE=$(date +%Y%m%d)
RETENTION_DAYS=30

# 需要备份的目录
declare -A DIRS
DIRS["projects"]="$HOME/projects"
DIRS["configs"]="/etc"
DIRS["notes"]="$HOME/notes"

echo "=== 开始备份: $DATE ==="

# 创建备份目录
mkdir -p "$BACKUP_ROOT/$DATE"

for name in "${!DIRS[@]}"; do
    src="${DIRS[$name]}"
    dest="$BACKUP_ROOT/$DATE/$name.tar.gz"
    
    if [ -d "$src" ]; then
        echo "备份 $src → $dest"
        tar -czf "$dest" \
            --exclude="node_modules" \
            --exclude=".git" \
            --exclude="*.log" \
            "$src" 2>/dev/null
        echo "  ✅ $(du -h "$dest" | cut -f1)"
    else
        echo "  ⚠️ 目录不存在: $src"
    fi
done

# 删除过期备份
echo ""
echo "清理 $RETENTION_DAYS 天前的备份..."
find "$BACKUP_ROOT" -maxdepth 1 -type d -mtime +$RETENTION_DAYS -exec rm -rf {} \;

echo "=== 备份完成 ==="

输出:

TEXT 📖 仅展示
=== 开始备份: 20260707 ===
备份 /home/alice/projects → /backup/20260707/projects.tar.gz
  ✅ 12M
备份 /etc → /backup/20260707/configs.tar.gz
  ✅ 4.5M
备份 /home/alice/notes → /backup/20260707/notes.tar.gz
  ✅ 256K

清理 30 天前的备份...
=== 备份完成 ===

▶ 综合示例:完整的 rsync 备份方案

BASH
#!/bin/bash
# rsync-backup.sh - 使用 rsync 的增量备份

SOURCE="$HOME/projects/webapp"
DEST_USER="backup"
DEST_HOST="backup.example.com"
DEST_PATH="/backups/webapp"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
LOGFILE="/var/log/backup.log"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOGFILE"
}

log "开始备份 $SOURCE..."

# 使用 rsync 进行远程增量备份
rsync -avz \
    --delete \
    --partial \
    --progress \
    --exclude="node_modules" \
    --exclude=".git" \
    --exclude=".env" \
    --exclude="tmp/" \
    -e "ssh -i ~/.ssh/backup_key -p 22" \
    "$SOURCE/" \
    "${DEST_USER}@${DEST_HOST}:${DEST_PATH}/current/" >> "$LOGFILE" 2>&1

if [ $? -eq 0 ]; then
    log "✅ 备份成功"
    # 创建带时间戳的快照
    ssh -i ~/.ssh/backup_key "${DEST_USER}@${DEST_HOST}" \
        "cp -al ${DEST_PATH}/current ${DEST_PATH}/${TIMESTAMP}"
    log "✅ 快照创建: $TIMESTAMP"
else
    log "❌ 备份失败 (exit code: $?)"
    exit 1
fi

❓ 常见问题

Q: tar 和 gzip 是什么关系? A: tar 只负责打包(将多个文件合并成一个),不压缩。gzip 负责压缩。常用组合 tar -czf 相当于 tar 打包 → gzip 压缩。扩展名 .tar.gz.tgz

Q: tar -czf 中的 -c-z-f 分别代表什么? A: -c(create)创建归档,-z(gzip)通过 gzip 压缩,-f(file)指定归档文件名。简写 tar -czf 也可以写成 tar -c -z -f

Q: zip 和 tar.gz 哪个跨平台更好? A: zip 的跨平台兼容性更好——Windows/macOS/Linux 都原生支持。tar.gz 是 Linux/Unix 世界的标准,Windows 需要第三方工具(如 7-Zip)。

Q: rsync 比 scp 快在哪? A: \1

Q: 怎么增量备份而不是全量? A: rsync 本身只传增量(变化的部分)。结合 --link-dest 创建硬链接快照:第一次全量,之后每天用 --link-dest 引用前一天的快照,只存储变化的部分。


📖 小节


📝 作业

  1. 基础题(难度⭐):将 ~/projects 或一个测试目录打包为 backup.tar.gz,用 -v 观察过程,然后用 tar -tf 查看包内文件列表
  2. 进阶题(难度⭐⭐):解压到 /tmp/test 目录并验证文件完整性,然后创建一个测试目录,用 zip 打包(排除某个子目录)并用 unzip 解压到另一处
  3. 挑战题(难度⭐⭐⭐):用 rsync 将本地一个目录同步到 /tmp/backup/,验证增量传输(修改一个文件后再同步,观察只传输了变化部分),然后写一个备份脚本支持 tar.gz 全量备份和 rsync 增量备份两种模式
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏