8.1 压缩文件的用途与技术
两种压缩原理:
- 去冗余 bit:存数字 1 只占 1 bit,但文件系统按 Byte(8 bits)分配——7 个 bit 浪费了。压缩算法把这些”空位”挤掉
- 去重复:100 个连续的 1 → 存成”100×1”而非真写 100 个 1
压缩文件不能直接被 OS 使用,必须先解压缩。压缩比 = 压缩后/压缩前。
实际压缩效果:Linux 3.10.81 核心源码 570MB → 压缩后仅 76MB 左右(纯文本文件的”多余空间”最多)。现在很多网站传输时自动压缩、客户端再解压——CPU 运算很快,瓶颈在网络带宽。
8.2 Linux 系统常见的压缩指令
扩展名约定(Linux 文件属性不依赖扩展名,这些约定纯粹为了人类识别——不同压缩工具互不兼容):
| 扩展名 | 工具 | 地位 |
|---|---|---|
*.Z | compress | 已淘汰(gzip 可解,znew 可转格式) |
*.gz | gzip | GNU 出品,最普及 |
*.bz2 | bzip2 | GNU 出品,更高压缩比 |
*.xz | xz | 压缩比最高,但也最慢 |
*.tar | tar 打包 | 不压缩!仅打包 |
*.tar.gz / *.tgz | tar + gzip | 最常见格式 |
*.tar.bz2 | tar + bzip2 | |
*.tar.xz | tar + xz |
三大压缩指令只能压缩单个文件——多个文件必须先 tar 打包再压缩,所以
.tar.gz才是日常标配。
8.2.1 gzip, zcat/zmore/zless/zgrep
gzip 是应用最广的压缩指令,可解 compress、zip 与 gzip 格式。.gz 文件在 Windows 上 WinRAR/7zip 也能解。
gzip [-cdtv#] 文件名
# -c: 输出到 stdout; -d: 解压缩; -t: 检验完整性
# -v: 显示压缩比; -#: 1最快 ~ 9最好(默认6)# 压缩——原文件消失,变成 file.gz(和 Windows 压缩软件最大的差异!)
gzip -v services # services: 79.7% -- replaced with services.gz
# 解压缩
gzip -d services.gz # gunzip 等价,但鸟哥建议统一用 gzip -d
# 最高压缩比+保留原文件
gzip -9 -c services > services.gz # -c 输出到 stdout,> 重导向存盘
# 不解压直接查看文本
zcat services.gz # = 解压后 cat
zmore/zless services.gz # 翻页查看
zgrep -n 'http' services.gz # 不解压搜索关键词8.2.2 bzip2, bzcat/bzmore/bzless/bzgrep
bzip2 为取代 gzip 而来,用法几乎一样,多了一个 -k(保留原文件)。压缩比更好(同样文件 gzip 79.7% → bzip2 81.5%),但耗时约 2 倍。
bzip2 [-cdkzv#] 文件名
bzip2 -v services # 压缩 → services.bz2, 原文件消失
bzip2 -d services.bz2 # 解压缩
bzip2 -k services # 压缩且保留原文件
bzip2 -9 -c services > services.bz2 # 最高压缩+保留原文件
bzcat/bzmore/bzless services.bz2 # 不解压查看8.2.3 xz, xzcat/xzmore/xzless/xzgrep
xz 压缩比最高,比 bzip2 更省空间,但耗时暴增 10 倍。-l 可列出压缩前后信息(独有功能)。
xz [-dtlkc#] 文件名
xz -v services # 压缩 → services.xz(gzip 21% vs xz 15%!)
xz -d services.xz # 解压缩
xz -k services # 保留原文件
xz -l services.xz # 列出压缩前后容量和压缩比
xzcat services.xz # 不解压查看
# 实测(用 time 对比压缩 28MB /etc):
# gzip: 0.019s, 压缩后 7.7MB
# bzip2: 0.042s, 压缩后 6.7MB
# xz: 0.261s, 压缩后 5.5MB选型:日常用 gzip(快)、归档存长期用 xz(小)、折中用 bzip2。
8.3 打包指令: tar
gzip/bzip2/xz 只能压单个文件。tar(tape archive)将多个文件/目录打包成一个大文件,再加 -z/-j/-J 调用对应压缩。Windows 的 WinRAR 也支持 .tar.gz。
8.3.1 tar
tar [-z|-j|-J] [cv] [-f 新文件名] filename... # 打包+压缩
tar [-z|-j|-J] [tv] [-f 已有tar文件名] # 查看内容
tar [-z|-j|-J] [xv] [-f 已有tar文件名] [-C 目录] # 解包| 选项 | 含义 |
|---|---|
-c | 创建(create);-t 查看(list);-x 解包(extract)——三选一 |
-z | gzip;-j bzip2;-J xz —— 三选一 |
-v | 显示处理中的文件名 |
-f filename | 指定包文件名——必须紧跟文件名!建议 -f 单独写 |
-C 目录 | 解压到指定目录 |
-p | 保留原本权限与属性(备份必备!) |
-P | 保留绝对路径(危险!一般不推荐) |
--exclude=FILE | 排除指定文件 |
--newer-mtime=日期 | 只打包指定日期之后变更的文件(差异备份) |
# 基本三件套
tar -jcv -f file.tar.bz2 /etc # 打包+bzip2
tar -jtv -f file.tar.bz2 # 查看包内容
tar -jxv -f file.tar.bz2 -C /tmp # 解包到 /tmp-f 的经典坑:tar -jcvf file.tar.bz2 正确;tar -jvfc file.tar.bz2 则输出文件名变成 c(因为 -fc)。建议把 -f 单独写。
默认去掉根目录 /——安全设计:打包 /etc 后,包内文件名是 etc/passwd 而非 /etc/passwd。如果保留 /,在 /tmp 解开会直接覆盖系统 /etc!若确实需要保留绝对路径加 -P(大写),但强烈不推荐。
# 实际备份 /etc 对比三种格式
time tar -zpcv -f /root/etc.tar.gz /etc # gzip: 0.8s, 7.7MB
time tar -jpcv -f /root/etc.tar.bz2 /etc # bzip2: 1.9s, 6.7MB
time tar -Jpcv -f /root/etc.tar.xz /etc # xz: 9.0s, 5.5MB
# 注意警告 "Removing leading `/' from member names"仅解包单一文件:先用 -jtv | grep 找到包内路径 → 用该路径解出(注意不以 / 开头)。
tar -jtv -f /root/etc.tar.bz2 | grep 'shadow'
tar -jxv -f /root/etc.tar.bz2 etc/shadow排除文件:
tar -jcv -f /root/system.tar.bz2 --exclude=/root/etc* \
--exclude=/root/system.tar.bz2 /etc /root差异备份(—newer-mtime):
tar -jcv -f new.tar.bz2 --newer-mtime="2015/06/17" /etc/*
# --newer-mtime 只比较 mtime;--newer 同时比较 mtime+ctime
# 未变更的文件最后显示 "file is unchanged; not dumped"管线打包——不产生中间文件:
cd /tmp
tar -cvf - /etc | tar -xvf -
# - 代表 stdout/stdin,通过管线在内存中传递,类似 cp -r系统备份范例:
mkdir /backups; chmod 700 /backups
tar -jcv -f /backups/backup-system-$(date +%Y%m%d).tar.bz2 \
--exclude=/root/*.gz --exclude=/home/loop* \
/etc /home /var/spool/mail /var/spool/cron /root术语:tarfile = 纯打包不压缩(*.tar),tarball = 打包且压缩(*.tar.gz 等)。
tar 还原后 SELinux 陷阱:还原系统文件(如 /etc/shadow)后 SELinux 安全上下文被破坏→可能无法登录。三种修复:① 重启前 restorecon -Rv /etc(最推荐);② 改 /etc/selinux/config → permissive;③ 创建 /.autorelabel 重启。
8.4 XFS 文件系统的备份与还原
tar 针对目录树备份;xfsdump 针对整个文件系统(partition)级别备份。
8.4.1 XFS 文件系统备份 xfsdump
五条限制:① 只能备份已挂载的文件系统;② 需要 root 权限;③ 只能备份 XFS;④ 备份出的数据只能由 xfsrestore 解析;⑤ 靠 UUID 识别,不能备份两个相同 UUID 的文件系统;⑥ 只能备份整个文件系统(如 /boot),不能备份普通目录(如 /etc)。
完整备份与累积备份:level 0 = 完整备份;level 1~9 = 累积(增量)备份。level 1 只备份与 level 0 的差异;level 2 只备份与 level 1 的差异。备份记录在 /var/lib/xfsdump/inventory/。
# 先确认是独立文件系统
df -h /boot # → /dev/vda2
# level 0 完整备份
xfsdump -l 0 -L boot_all -M boot_all -f /srv/boot.dump /boot
# level 1 累积备份(只会备份新增/修改的文件)
dd if=/dev/zero of=/boot/testing.img bs=1M count=10 # 模拟变更
xfsdump -l 1 -L boot_2 -M boot_2 -f /srv/boot.dump1 /boot
# 观察文件大小: boot.dump ≈ 98MB, boot.dump1 ≈ 10MB(正好是新增文件大小!)
# 查看所有备份记录
xfsdump -I # 输出含 session id, level, label, time, pathname8.4.2 XFS 文件系统还原 xfsrestore
xfsrestore -I # 查看备份记录(同 xfsdump -I)
# 完整还原 level 0
xfsrestore -f /srv/boot.dump -L boot_all /boot
# 注意:同名文件被覆盖,但原位置**新增的文件不会被删除**
# 还原到其他位置查看
xfsrestore -f /srv/boot.dump -L boot_all /tmp/boot
# 只还原包内某一个目录
xfsrestore -f /srv/boot.dump -L boot_all -s grub2 /tmp/boot2
# 累积还原:先 level 0 再 level 1
xfsrestore -f /srv/boot.dump -L boot_all /tmp/boot
xfsrestore -f /srv/boot.dump1 /tmp/boot
# 互动模式(不知道包里有啥时用 -i 进入交互界面选择文件)
xfsrestore -f /srv/boot.dump -i /tmp/boot3
# 进入后可 ls, cd, add, delete, extract8.5 光盘写入工具
8.5.1 mkisofs:创建镜像文件
mkisofs [-o 镜像文件] [-Jrv] [-V vol] [-m file] [-graft-point isodir=systemdir ...] 待备份文件...
# -o: 输出 ISO 文件名
# -r: 通过 Rock Ridge 记录 UID/GID 等 Unix 文件信息
# -J: 兼容 Windows 的长文件名(最长 64 Unicode 字符)
# -V: Volume 名称(类似 Windows 光盘标题)
# -m: 排除文件(支持通配符)
# -graft-point: 指定镜像内目录结构注意:不同目录下有同名文件(如 /root/crontab 和 /etc/crontab)时 mkisofs 会报错——因为光盘的 iso9660 文件系统不允许同名。
# 简单打包——所有文件堆在根目录(不推荐)
mkisofs -r -v -o /tmp/system.img /root /home /etc
# 使用 -graft-point 指定镜像内目录结构(推荐)
mkisofs -r -V 'linux_file' -o /tmp/system.img \
-m /root/etc -graft-point /root=/root /home=/home /etc=/etc
# 验证:挂载 ISO 查看
mount -o loop /tmp/system.img /mnt && ls /mnt && umount /mnt制作可开机光盘:从原版 ISO 提取内容 → 修改 → 重建时加 -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot 等开机参数。详细流程见原书。
8.5.2 cdrecord:光盘烧录工具
CentOS 7 使用 wodim(兼容 cdrecord)。
wodim --devices dev=/dev/sr0 # 侦测烧录机位置
wodim -v dev=/dev/sr0 blank=fast # 抹除可复写光盘(-v 显示过程)
wodim -v dev=/dev/sr0 speed=4 -eject /tmp/system.img # 烧录(-eject 完成后自动弹出)
# 非可复写光盘省略 blank 步骤8.6 其他常见的压缩与备份工具
8.6.1 dd
dd 逐扇区读取,不认文件系统——连未使用扇区也写入,备份文件 = 分区总容量(不管实际用了多少)。优势是任何文件系统格式都能备份/还原。
dd if="input_file" of="output_file" bs="block_size" count="number"
# bs 默认 512 Bytes(一个扇区)
# 备份文件
dd if=/etc/passwd of=/tmp/passwd.back
# 光盘 → 镜像文件
dd if=/dev/sr0 of=/tmp/system.iso
# 镜像 → USB 磁盘(制作启动盘!)
dd if=/tmp/system.iso of=/dev/sda # 注意:of 是整个磁盘不是分区!
# 备份整个分区——文件大小 = 分区总容量
dd if=/dev/vda2 of=/tmp/vda2.img # 1GB 分区 → 1GB 文件
# 完整复制分区(包括 boot sector)
# 先 fdisk 创建相同大小的分区,再 dd 复制dd 做 USB 启动盘是最经典的用途——比任何工具都快,一行搞定。
8.6.2 cpio
cpio 可以备份任何文件(包括 /dev 下的设备文件),但不会自己找文件——必须配合 find 等指令提供文件列表。
cpio -ovcB > [file|device] # 备份(-o=output, -v=verbose, -c=统一格式, -B=加速读写)
cpio -ivcdu < [file|device] # 还原(-i=input, -d=自动创建目录, -u=覆盖旧文件)
cpio -ivct < [file|device] # 查看内容(-t=查看)# 备份 /boot 下所有文件
cd /
find boot | cpio -ocvB > /tmp/boot.cpio
# 注意:必须 cd 到 / 再 find boot(不能用 find /boot),因为 cpio 不认绝对路径
# 查看备份内容
cpio -ivct < /tmp/boot.cpio
# 还原
cd /
cpio -idvc < /tmp/boot.cpio
# 整盘备份到磁带机
find / | cpio -ocvB > /dev/st0
cpio -idvc < /dev/st0initramfs(
/boot/initramfs-xxx.img)就是用 cpio 打包的!file检查其类型会显示 “ASCII cpio archive”。
关键命令
| 命令 | 用途 |
|---|---|
gzip -v/-d/-c | 压缩/解压 .gz |
zcat/zgrep | 不解压查看/搜索 .gz |
bzip2 -v/-d/-k | 压缩/解压 .bz2 |
xz -v/-d/-k/-l | 压缩/解压 .xz |
tar -jcv -f | bzip2 打包 |
tar -jtv -f | 查看包内容 |
tar -jxv -f -C | 解包到指定目录 |
tar --exclude / --newer-mtime | 排除/差异备份 |
xfsdump -l N -L label -f | XFS 备份(level 0~9) |
xfsdump -I | 查看备份记录 |
xfsrestore -f -L -s | XFS 还原(-s 指定子目录,-i 互动模式) |
mkisofs -r -o -graft-point | 创建 ISO 镜像 |
wodim -v dev=/dev/sr0 | 光盘烧录 |
dd if= of= bs= | 扇区级复制(做 USB 启动盘) |
cpio -ovcB / cpio -idvc | 配合 find 备份/还原 |
restorecon -Rv /etc | 修复 SELinux 上下文 |