第八章、文件与文件系统的压缩、打包与备份 8.1 压缩文件的用途与技术 为什么需要压缩
节省存储空间 :压缩后的文件占用更少的磁盘空间
提高传输效率 :网络传输时减少时间和带宽消耗
归档备份 :将多个文件打包成单一文件便于管理
压缩的原理 压缩通过消除数据中的冗余信息来减小文件大小:
无损压缩 :可以完全恢复原始数据(gzip、bzip2、xz)
有损压缩 :牺牲部分质量换取更高压缩率(jpeg、mp3)
8.2 Linux 系统常见的压缩指令 常见压缩工具对比
工具
扩展名
压缩率
速度
特点
gzip
.gz
中等
快
最常用,兼容性好
bzip2
.bz2
高
慢
压缩率优于 gzip
xz
.xz
最高
最慢
现代压缩标准
zip
.zip
中等
快
Windows 兼容
compress
.Z
低
快
已过时,很少使用
gzip 和 zcat gzip - 最流行的压缩工具:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 gzip filename gzip -c filename > filename.gz gzip -k filename gunzip filename.gz -1 ... -9 -c -d -f -h -k -l -L -n -N -q -r -t -v -V gzip -9 -k largefile.txt gzip -r /path/to/directory/ gzip -l file.gz gzip -t file.gz
zcat/zmore/zless - 不解压查看压缩文件:
1 2 3 4 5 6 7 8 9 10 11 zcat file.gz zmore file.gz zless file.gz zgrep "pattern" file.gz gzcat file.gz > output.txt zcat file.gz | grep pattern
bzip2 和 bzcat bzip2 - 更高压缩率:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 bzip2 filename bzip2 -k filename bzip2 -c filename > filename.bz2 bunzip2 filename.bz2 -1 ... -9 -c -d -f -k -s -t -v -z bzip2 -9 -k largefile.txt bzip2 -t file.bz2
bzcat/bzmore/bzless/bzgrep:
1 2 3 4 5 6 7 8 bzcat file.bz2 bzmore file.bz2 bzless file.bz2 bzgrep "pattern" file.bz2 bzgrep "pattern" *.bz2
xz 和 xzcat xz - 最高压缩率(现代标准):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 xz filename xz -k filename xz -c filename > filename.xz unxz filename.xz -0 ... -9 -e -c -d -f -k -l -t -v -T NUM xz -9 -k largefile.txt xz -T4 largefile.txt xz -e file.txt xz -l file.xz
xzcat/xzmore/xzless/xzgrep:
1 2 3 4 5 6 7 8 xzcat file.xz xzmore file.xz xzless file.xz xzgrep "pattern" file.xz xzgrep "pattern" *.xz
压缩工具对比示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 dd if =/dev/zero of=test.file bs=1M count=100time gzip -k test.filetime bzip2 -k test.filetime xz -k test.filels -lh test.file*
8.3 打包指令:tar tar 命令概述 tar(Tape Archive)是 Linux/Unix 系统中最常用的归档工具,将多个文件或目录打包成单一文件(称为 tar 归档或 tarball),常与压缩工具结合使用。
tar 的特点:
保留文件的权限、所有者、时间戳等信息
支持多种压缩格式
可以增量备份
支持远程备份
tar 基本语法 1 tar [选项] [归档文件] [文件或目录...]
常用选项 操作模式(必须选其一):
选项
功能
-c
创建新的归档文件 (create)
-x
从归档中提取文件 (extract)
-t
列出归档内容 (list)
-r
追加文件到归档末尾 (append)
-u
仅追加比归档中更新的文件 (update)
-A
将另一个 tar 归档追加到当前归档
-d
比较归档和文件系统的差异 (diff)
--delete
从归档中删除文件
常用通用选项:
选项
功能
-v
详细模式,显示处理过程 (verbose)
-f
指定归档文件名,必须后跟文件名
-p
保留原始文件权限和属性 (preserve)
-P
使用绝对路径(小心使用)
-C
切换到指定目录再执行操作
-z
使用 gzip 压缩/解压缩 (.gz)
-j
使用 bzip2 压缩/解压缩 (.bz2)
-J
使用 xz 压缩/解压缩 (.xz)
--exclude
排除特定文件或目录
--exclude-from
从文件中读取排除列表
--files-from
从文件中读取要处理的文件列表
-h
显示帮助信息
--version
显示版本信息
tar 实战示例 1. 创建归档:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 tar -cvf archive.tar /path/to/directory tar -czvf archive.tar.gz /path/to/directory tar -czvf backup-$(date +%Y%m%d).tar.gz ~/Documents tar -cjvf archive.tar.bz2 /path/to/directory tar -cJvf archive.tar.xz /path/to/directory tar -czvf backup.tar.gz /home/user --exclude='*.log' --exclude='*.tmp' --exclude='cache' tar -czvf backup.tar.gz /home/user --exclude-from=exclude.list tar -czvf scripts.tar.gz /home/user --include='*.sh' --include='*.py' tar -czvf backup.tar.gz /etc/nginx /var/www /home/user/config tar -czvpf backup.tar.gz --same-owner /important/data tar -czvf backup-$(date +%Y%m%d_%H%M%S).tar.gz /data tar -czN "2024-01-01" -f recent.tar.gz /data tar -czf - /local/data | ssh user@remote "cat > /backup/data.tar.gz"
2. 查看归档内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 tar -tvf archive.tar tar -tzvf archive.tar.gz tar -tjvf archive.tar.bz2 tar -tzf archive.tar.gz | grep "pattern" tar -tvf archive.tar path/to/file tar -tvf archive.tar --wildcards "*.txt"
3. 解压归档:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 tar -xvf archive.tar tar -xzvf archive.tar.gz tar -xzf archive.tar.gz tar -xjvf archive.tar.bz2 tar -xJvf archive.tar.xz tar -xzvf archive.tar.gz -C /path/to/destination tar -xzvf archive.tar.gz path/to/specific/file tar -xzvf archive.tar.gz --wildcards "*.txt" tar -xzvpf archive.tar.gz sudo tar -xzvpf archive.tar.gz --same-ownertar -xvf archive.tar --checkpoint=1000 --checkpoint-action=echo ="Extracted %u files" cat archive.tar.gz | ssh user@remote "tar -xzvf - -C /destination"
4. 追加和更新归档:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 tar -rvf archive.tar newfile.txt tar -rvf archive.tar /path/to/new/directory/ tar -uvf archive.tar updatedfile.txt tar -Af archive1.tar archive2.tar gunzip archive.tar.gz tar -rvf archive.tar newfile gzip archive.tar
5. 删除归档中的文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 tar --delete -f archive.tar file_to_delete.txt tar --delete -f archive.tar "*.log" tar --delete -f archive.tar file1 file2 file3 tar -xzvf archive.tar.gz rm file_to_delete.txt tar -czvf new_archive.tar.gz *
6. 从归档中提取特定文件:
1 2 3 4 5 6 7 8 9 10 11 12 tar -xzvf archive.tar.gz path/to/file.txt tar -xzvf archive.tar.gz file1.txt file2.txt tar -xzvf archive.tar.gz --wildcards "*.txt" tar -xzvf archive.tar.gz --wildcards "data/*.csv" tar -xzvf archive.tar.gz -C /destination/directory file.txt
7. 特殊用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 tar -czf - /local/dir | ssh user@remote "cat > /backup/backup.tar.gz" rsync -avz /local/dir/ user@remote:/backup/ cat backup.tar.gz | ssh user@remote "cat > -" | tar -xzf -tar -czf backup-full.tar.gz --listed-incremental=snapshot.file /data tar -czf backup-incr.tar.gz --listed-incremental=snapshot.file /data cat archive1.tar archive2.tar > combined.tartar -czvf - /large/directory | split -b 1G - backup.tar.gz. cat backup.tar.gz.* | tar -xzvf -tar -czPvf backup.tar.gz /etc /var/log tar -czvf backup.tar.gz /home --exclude='*.mp4' --exclude='cache' --exclude-vcs
压缩工具详解 gzip 详解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 dd if =/dev/urandom of=testfile bs=1M count=100for level in 1 6 9; do time gzip -${level} -c testfile > testfile.gz.${level} ls -lh testfile.gz.${level} done gzip -l testfile.gz find /path/to/dir -type f -exec gzip {} \; find /path/to/dir -type f | xargs gzip
bzip2 详解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 for tool in gzip bzip2; do echo "Testing $tool ..." time $tool -k testfile ls -lh testfile.* $tool -d testfile.* done bzip2recover corrupted.bz2 pbzip2 -p4 file
xz 详解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 for level in 0 6 9; do echo "Testing xz -$level ..." time xz -${level} -k -c testfile > testfile.xz.${level} ls -lh testfile.xz.${level} done xz -T4 file pxz -9 file xz -l file.xz xz -t file.xz xz --lzma2=preset=9,dict=64MiB file
现代压缩工具 zstd - 快速压缩 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 sudo yum install zstd sudo apt install zstd zstd -1 file zstd -9 file zstd -19 file zstd --ultra -22 file zstd -T4 file zstd -T0 file zstd -d file.zst unzstd file.zst zstdcat file.zst zstdgrep pattern file.zst zstdless file.zst for level in 1 3 9; do time zstd -${level} -k -c testfile > testfile.zst.${level} ls -lh testfile.zst.${level} done
pigz - 并行 gzip 1 2 3 4 5 6 7 8 9 10 sudo yum install pigzpigz file pigz -p 4 file unpigz file.gz
pbzip2 - 并行 bzip2 1 2 3 4 5 6 7 8 sudo yum install pbzip2pbzip2 file pbzip2 -p4 file pbzip2 -d file.bz2
压缩性能对比测试脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 #!/bin/bash TEST_FILE="benchmark_test_file" FILE_SIZE="100M" echo "Creating test file (${FILE_SIZE} )..." dd if =/dev/urandom of=${TEST_FILE} bs=1M count=100 status=progressecho "" echo "==========================================" echo "Compression Benchmark" echo "==========================================" echo "Original file size: $(ls -lh ${TEST_FILE} | awk '{print $5}') " echo "" echo "--- gzip ---" for level in 1 6 9; do echo -n "Level ${level} : " time (gzip -${level} -k -c ${TEST_FILE} > ${TEST_FILE} .gz.${level} ) ls -lh ${TEST_FILE} .gz.${level} | awk '{print "Size:", $5}' rm -f ${TEST_FILE} .gz.${level} done echo "" if command -v pigz &> /dev/null; then echo "--- pigz (parallel gzip) ---" echo -n "Default (all cores): " time (pigz -k -c ${TEST_FILE} > ${TEST_FILE} .pigz) ls -lh ${TEST_FILE} .pigz | awk '{print "Size:", $5}' rm -f ${TEST_FILE} .pigz echo "" fi if command -v bzip2 &> /dev/null; then echo "--- bzip2 ---" echo -n "Default: " time (bzip2 -k -c ${TEST_FILE} > ${TEST_FILE} .bz2) ls -lh ${TEST_FILE} .bz2 | awk '{print "Size:", $5}' rm -f ${TEST_FILE} .bz2 echo "" fi if command -v pbzip2 &> /dev/null; then echo "--- pbzip2 (parallel bzip2) ---" echo -n "Default: " time (pbzip2 -k -c ${TEST_FILE} > ${TEST_FILE} .pbz2) ls -lh ${TEST_FILE} .pbz2 | awk '{print "Size:", $5}' rm -f ${TEST_FILE} .pbz2 echo "" fi if command -v xz &> /dev/null; then echo "--- xz ---" for level in 0 6 9; do echo -n "Level ${level} : " time (xz -${level} -k -c ${TEST_FILE} > ${TEST_FILE} .xz.${level} ) ls -lh ${TEST_FILE} .xz.${level} | awk '{print "Size:", $5}' rm -f ${TEST_FILE} .xz.${level} done echo "" fi if command -v zstd &> /dev/null; then echo "--- zstd ---" for level in 1 3 9 19; do echo -n "Level ${level} : " time (zstd -${level} -k -c ${TEST_FILE} > ${TEST_FILE} .zst.${level} ) ls -lh ${TEST_FILE} .zst.${level} | awk '{print "Size:", $5}' rm -f ${TEST_FILE} .zst.${level} done echo "" fi echo "==========================================" echo "Cleaning up..." rm -f ${TEST_FILE} ${TEST_FILE} .*echo "Done!"
使用 tar 进行完整系统备份 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 #!/bin/bash BACKUP_DIR="/backup" DATE=$(date +%Y%m%d_%H%M%S) HOSTNAME=$(hostname) BACKUP_FILE="${BACKUP_DIR} /${HOSTNAME} _full_backup_${DATE} .tar.gz" EXCLUDE_LIST=( "${BACKUP_DIR} " "/proc" "/sys" "/dev" "/run" "/mnt" "/media" "/tmp" "/var/tmp" "/var/cache" "/var/log" "*.swap" "*/lost+found" ) EXCLUDE_ARGS="" for item in "${EXCLUDE_LIST[@]} " ; do EXCLUDE_ARGS+="--exclude=${item} " done mkdir -p "${BACKUP_DIR} " echo "========================================" echo "Starting Full System Backup" echo "Backup file: ${BACKUP_FILE} " echo "Started at: $(date) " echo "========================================" tar -czvpf "${BACKUP_FILE} " \ ${EXCLUDE_ARGS} \ --one-file-system \ / 2>"${BACKUP_FILE} .log" if [ $? -eq 0 ]; then echo "========================================" echo "Backup completed successfully!" echo "Backup file: ${BACKUP_FILE} " echo "Backup size: $(du -h "${BACKUP_FILE} " | cut -f1) " echo "Completed at: $(date) " echo "========================================" cd "${BACKUP_DIR} " || exit ls -t "${HOSTNAME} _full_backup_" *.tar.gz | tail -n +6 | xargs -r rm -f exit 0 else echo "========================================" echo "Backup failed!" echo "Check log file: ${BACKUP_FILE} .log" echo "Failed at: $(date) " echo "========================================" exit 1 fi
使用 tar 进行增量备份 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #!/bin/bash SOURCE_DIR="/data" BACKUP_DIR="/backup/incremental" DATE=$(date +%Y%m%d_%H%M%S) SNAPSHOT_FILE="${BACKUP_DIR} /.snapshot" mkdir -p "${BACKUP_DIR} " tar -czvpf "${BACKUP_DIR} /incr_${DATE} .tar.gz" \ --listed-incremental="${SNAPSHOT_FILE} " \ "${SOURCE_DIR} " find "${BACKUP_DIR} " -name "incr_*.tar.gz" -mtime +7 -delete echo "Incremental backup completed: ${BACKUP_DIR} /incr_${DATE} .tar.gz"
恢复备份 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 tar -xzvpf backup.tar.gz -C / tar -xzvpf backup.tar.gz -C /restore tar -xzvpf backup.tar.gz path/to/specific/file tar -xzvpf backup.tar.gz --wildcards "etc/nginx/*" sudo tar -xzvpf backup.tar.gz -C / --same-ownertar -xzvpf full_backup.tar.gz -C / for backup in incr_*.tar.gz; do tar -xzvpf "$backup " -C / done checksum_file="checksum.list" if [ -f "$checksum_file " ]; then md5sum -c "$checksum_file " fi
8.4 重点回顾
压缩工具 :
gzip:速度快,兼容性好,压缩率中等
bzip2:压缩率更高,速度较慢
xz:压缩率最高,速度最慢
zstd:速度极快,现代压缩标准
tar 命令 :
-c 创建,-x 解压,-t 查看,-v 详细,-f 指定文件
-z gzip,-j bzip2,-J xz 压缩
--exclude 排除文件,--wildcards 通配符
备份策略 :
完整备份:备份所有数据
增量备份:只备份变化的文件
差异备份:备份自上次完整备份后变化的文件
实用技巧 :
管道和 SSH 实现远程备份
使用 find 和 tar 实现精细控制
定期清理旧备份
定期测试备份的可恢复性
8.5 本章习题
对比 gzip、bzip2、xz 三种压缩工具的压缩率和速度。
如何使用 tar 命令创建一个包含 /etc 目录的压缩归档,排除所有 .log 文件?
如何不解压查看 tar.gz 文件的内容?
编写一个脚本,每天自动备份 /home 目录,保留最近7天的备份。
如何使用 tar 和 ssh 将本地目录备份到远程服务器?
解释 tar 的增量备份功能,如何创建和恢复增量备份?
比较 zip 和 tar.gz 的异同,什么时候应该使用 zip?
有一个损坏的 tar.gz 文件,如何尝试恢复其中的数据?
8.6 参考资料与延伸阅读