开头
系统备份这件事,绝大多数Ubuntu用户的态度是“不折腾,不备份”,我自己也是从一次灾难性事故中才彻底改过来的。当时刚接触Linux没多久,稀里糊涂把某台跑着个人网站和数据库的机器搞崩了,启动直接进不了系统,数据全在那块盘里,折腾了一整天才勉强把home目录拷出来,丢了不少最近的日志和数据库记录。从那以后,“备份、恢复、迁移”这三个词就成了我使用Ubuntu时最优先考虑的问题——不管你是普通桌面用户、折腾虚拟机的人,还是管着几台服务器的运维,这套东西迟早用得上。
这篇博文是“跟韩工学Ubuntu”系列第9章的第三篇,聚焦的是系统备份、恢复与迁移的完整落地方法。和前面讲安装、讲日常使用不同,这章内容偏“保命型”:平时用不上,真到出事那天,你按这几条路线走,能少流很多泪。文章不会只给你几个命令就完事,而是会把“为什么要这么备份”“不同场景该选哪种方案”“恢复时最容易踩什么坑”讲透,我还会把我实操中踩过的坑、做过的测试全部写进去。
无论你是刚装好Ubuntu的桌面用户,还是手里管着几台虚拟机的学习者,或是准备把老旧系统迁移到新服务器、新架构的从业者,这篇都能直接当手册用。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
1. 内容整体设计与思路拆解
1.1 备份的本质:你在防什么
很多人一说到“备份”,第一反应是把整个系统盘做成镜像,类似Windows下的Ghost。但这其实是最重、最笨的一种方案。备份之前先想清楚一个问题:你到底在防什么?
我的答案是分三层。第一层是防“文件误删”,比如手滑 rm -rf 了重要目录,或者 mv 之后重启发现文件找不到了;第二层是防“系统崩溃”,比如内核升级失败、显卡驱动装挂、启动引导损坏,这些情况下系统进不去,但磁盘本身还好;第三层是防“硬件损坏或整体迁移”,比如硬盘坏道蔓延、要换机器、要把系统从机械盘搬到SSD,或者要从虚拟机迁到物理机。
三层风险对应的是三种完全不同的备份粒度。文件级备份最快、最常用,但救不了系统损坏;分区级镜像备份最彻底,但耗时长、恢复麻烦、兼容性差;中间还有一种“系统状态备份”,专门保存已安装软件、系统配置、网络设置这些环境信息,这一层很多人容易忽略,其实恢复起来最痛苦的就是它。
我在实际使用中的思路是:日常跑着的机器,按“文件级+系统状态级”双重备份;有特殊任务或要及时交付的项目,在关键节点再做一次完整镜像。这样既不浪费磁盘空间,又能保证绝大部分真实风险被覆盖到。
1.2 工具选型逻辑:rsync、tar、dd,怎么分
Ubuntu下做备份的常用工具有三个:rsync、tar、dd。我见过不少教程把这三个工具混着讲,给人感觉就是“能备份就行”。但实际上,它们的定位差异非常大,选错工具会直接导致备份无效或者恢复困难。
rsync 是文件级同步器,擅长把目录“复制”成另一份一模一样的目录,可以增量同步、可以走SSH远程同步,适合做持续备份和数据迁移。tar 是打包器,擅长把一堆文件打包成单个归档文件,结合压缩可以做到体积小、易归档,适合做离线备份快照。dd 是块级复制器,直接按扇区复制整个磁盘或分区,不管文件系统、不管文件是否损坏,能克隆出一模一样的盘,但速度慢、体积大,适合做整机迁移。
这三者的关系可以打个比方:rsync 像是整理房间——按你的方式把东西一件件归类摆好;tar 像是把房间打包成一个个纸箱;dd 则是把整个房间连同墙壁地板一起铸成石膏模型。整理房间随时能住,打包装箱方便运输,石膏模型虽然占地方但最完整。
我自己的方案是:数据频繁变动、需要持续备份时用 rsync;固定时间点的完整归档用 tar;整机换盘、迁移系统时用 dd。配合起来使用,覆盖所有场景。
1.3 为什么强烈建议做“可验证”的备份
这是我吃过很多亏之后才总结出来的,也是最想传达给新手的一点:一个备份如果无法从里面恢复数据,那它跟不存在没有区别。
很多人会定期运行备份命令,看到日志里写着“successfully completed”就放心了。但真正到你手动跑恢复流程的那天,才会发现种种问题——比如备份文件被截断了、某个目录在备份时正被进程写入导致数据不一致、hard link被转成了普通文件、软件包管理器元数据缺失导致软件状态无法恢复。
所以我在设计这篇文章的实操路线时,每一条都会带“验证步骤”。备份完成后,至少可以做这几件事:一是检查备份日志有无报错;二是用 ls -l 看归档文件是否完整;三是更严格的,在临时目录解压部分文件确认内容可读;四是系统恢复完成后,重启进系统跑一遍常用功能再宣布“恢复成功”。
从某种角度讲,备份的价值不在“备份”这个动作,而在“恢复”这个验证。这也是为什么我一直说:没验证过的备份,和没备份没区别。
2. 核心细节解析与实操要点
2.1 rsync:增量同步与远程迁移的主力
rsync 是我用得最多的命令,没有之一。无论是本机把一个目录同步到另一个磁盘,还是通过网络把系统同步到新机器,rsync 都能胜任。它的核心优势是:只传输变化的部分,支持断点续传,还能保留权限、所有者、时间戳、软链接甚至ACL。
一个我常用的本机同步命令是这样的:
bash复制sudo rsync -aAXv --delete --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} / /mnt/backup/
拆解一下参数:-a 是归档模式,相当于 -rlptgoD,会保留权限、软链接、时间戳等信息;-A 保留ACL;-X 保留扩展属性(xattr),比如SELinux标签或用户自定义属性;-v 显示过程;--delete 让目标端删除源端已不存在的文件,保证目标端与源端完全一致。
排除目录那一长串是重点。备份系统根目录时,必须排除 /proc、/sys、/dev、/run 这些虚拟文件系统,它们的内容是运行时动态生成的,备份没有意义,甚至可能导致恢复后的系统异常。/tmp 可以视情况排除,里面的临时文件通常不需要保留;/lost+found 是文件系统损坏时的文件恢复目录,排除即可。
用了 --delete 需要特别小心。它只认目标端目录内的文件,不会主动删除目标端的其他内容,但它会把目标端有、源端没有的文件删掉。我用它做系统迁移时还会额外加一个 -n 参数做一次dry-run:
bash复制sudo rsync -aAXv --delete --dry-run / /mnt/backup/
先看模拟输出有没有问题,再真正执行。尤其注意是不是意外排除了某个重要目录,一旦 --delete 加上去,方向搞反了就是数据灾难。
远程迁移时,rsync 搭配SSH使用的命令长这样:
bash复制sudo rsync -aAXv --delete -e "ssh -p 22" /path/to/source user@remote-host:/path/to/dest
这种方式适合把整个服务器同步到另一台机器,第一次跑全量,之后每隔一段时间跑一次增量,最后在维护窗口再跑一次增量并切换。MySQL、PostgreSQL这类数据库的在线文件要注意,直接用 rsync 复制数据目录可能造成数据文件不一致,正确姿势是先做逻辑备份(如 mysqldump)或者使用文件系统快照。
2.2 tar:离线快照与归档的首选
tar 最适合的场景是:你有一个固定时间点,要把整个系统或某个大目录打包成一个可移动的文件。结合压缩可以节省大量空间,适合长期留档。
我常用的系统备份命令是:
bash复制sudo tar -cvpzf backup.tar.gz --exclude=/proc --exclude=/sys --exclude=/dev --exclude=/run --exclude=/tmp --exclude=/mnt --exclude=/media --exclude=/lost+found /
参数说明:-c 创建归档、-v 显示过程、-p 保留权限、-z 使用gzip压缩、-f 指定输出文件名。如果你是备份到外部硬盘或网络存储,可以不加 -z,用 -j(bzip2)或 -J(xz)换更高的压缩率,但代价是压缩耗时更长。我实际测过,一个约20GB的系统盘,gzip 压缩后大概7GB,耗时约半小时左右,换成 xz 压缩,压缩后5GB左右,耗时却要近两小时。一般建议用gzip,速度快、压缩比也够用。
tar 还有一个关键参数容易被忽略:--xattrs。它可以在打包时保留文件的扩展属性,很多桌面环境、软件管理器都会用xattr存东西,如果不带这个参数,恢复后可能某些应用行为异常。同样地,--acls 可以保留ACL权限。
我实际用的完整命令会加上这两个:
bash复制sudo tar -cvpzf /mnt/backup/system_backup_$(date +%F).tar.gz \
--xattrs --acls \
--exclude=/var/cache/apt/archives \
--exclude=/proc --exclude=/sys --exclude=/dev \
--exclude=/run --exclude=/tmp --exclude=/mnt \
--exclude=/media --exclude=/lost+found /
这里我把 /var/cache/apt/archives 也排除了,里面全是软件包的缓存文件,占了几个GB,恢复系统时重新用 apt update 下载就行,没必要备份。
恢复tar备份时,如果是恢复到同一套系统上,直接解包覆盖就行:
bash复制sudo tar -xvpzf /mnt/backup/system_backup_2025-01-05.tar.gz -C /
但需要注意,tar 恢复不会处理启动引导,所以要么配合Grub重装,要么只恢复文件层面,启动仍用原来完好的引导。还有一点:tar 恢复时因为保留权限,有些文件的属主可能不对,如果是在恢复系统里对不上,用 chown -R root:root / 这类命令统一修复即可。
2.3 dd:整盘克隆的利与弊
dd 是三个工具里最“物理”的。它直接读磁盘扇区,不管你用的是ext4、btrfs还是LVM,它只负责把二进制数据原封不动搬到另一个地方。这既是它的优点也是它的缺点。
缺点很明显:慢、占空间、无法增量。一个500GB的盘,无论上面装了多少数据,dd 都要把整个盘读完,备份到另一个同样大小的盘里,时间以小时计。
优点也很明显:完整、可靠、不需要关心文件系统细节。当你要更换硬盘、要把一个系统原封不动迁移到同容量的新盘时,dd 是最稳妥的方案。
整块磁盘克隆的命令是:
bash复制sudo dd if=/dev/sda of=/dev/sdb bs=64M conv=fsync status=progress
if 指定源盘,of 指定目标盘,bs 是块大小,64M 是实测性能较好的值,conv=fsync 确保数据落盘,status=progress 显示进度条。
但直接整个磁盘克隆有一个隐藏问题:如果新盘容量比源盘大,dd 只会复制跟源盘一样多的字节,新盘剩余空间不会被使用。这就需要在克隆完成后用 growpart 和 resize2fs 扩展分区和文件系统。如果你是给虚拟机磁盘扩容,这个步骤几乎一定会遇到。
如果只想备份单个分区,命令可以写成:
bash复制sudo dd if=/dev/sda1 of=/mnt/backup/sda1.img bs=64M conv=fsync status=progress
恢复时反向调换 if 和 of 即可。不过这种方式要求目标分区必须存在且大小不低于源分区,否则dd会直接报错或者造成数据截断。
还有一个经验:dd 恢复时如果源盘上有坏道,任务会卡住甚至中止。这个时候可以换 ddrescue,它能跳过坏道区域继续复制,虽然恢复出来的数据可能有部分文件损坏,但总比什么都拿不出来强。
3. 实操过程与核心环节实现
3.1 方案一:系统整体离线备份(tar + 外部驱动器)
我实际给Ubuntu桌面系统做离线备份时,流程大致是这样的。
准备阶段,先把要备份的系统挂载情况确认一遍。用 lsblk 或 df -h 查看磁盘布局,确认 root 分区在哪块盘上,有没有独立的 /home 分区,有没有双系统共用的EFI分区等。我遇到过有些朋友备份时把整块 /dev/sda 都打进去了,里面还包含着Windows分区,导致恢复时启动菜单混乱,备份文件也白白大了不少。
然后挂载备份用的外部驱动器。推荐使用USB3.0的外置SSD,速度比U盘快很多,容量也足够。挂载完用 df -h 确认挂载点路径:
bash复制sudo mount /dev/sdb1 /mnt/backup
接下来执行备份命令。由于系统文件在备份过程中可能被写入,尤其是正在运行的桌面环境和服务,所以最推荐的做法是从Live USB启动后再执行备份,这样系统处于停机状态,没有任何写入,备份结果最干净。如果你没有Live USB的条件,也可以在运行状态下备份,但需要接受文件可能有一点点不一致的风险。
我常用的备份命令是上面写过的 tar -cvpzf 那条。比较关键的一个操作是:备份完立即用 du -h 看归档文件大小,然后用 tar -tzf 列出归档内容做抽查:
bash复制sudo tar -tzf /mnt/backup/system_backup_2025-01-05.tar.gz | head -30
如果这里能看到 /etc/fstab、/etc/hostname 这类关键文件,基本可以确认备份内容可读。
恢复这个备份的方式是:Live USB启动,分区格式化,挂载目标分区到 /mnt/system,然后把归档解包进去:
bash复制sudo tar -xvpzf /mnt/backup/system_backup_2025-01-05.tar.gz -C /mnt/system
解完后还要重新绑定虚拟文件系统,然后chroot进系统里重新安装Grub引导,否则重启后系统不认这个新系统。具体流程在后面第四节细说。
3.2 方案二:在线同步与迁移(rsync)
如果你要迁移整个系统到新机器,或者要把数据持续同步到另一台服务器,用 rsync 比 tar 和 dd 都合适。
我的在线迁移流程分三步。第一步,在旧机器上先做一次全量同步,把整个系统同步到新机器。这里的新机器可以是另一台物理机、虚拟机或者局域网里的存储盘。全量同步代码如下:
bash复制sudo rsync -aAXv --delete \
--exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found","/swapfile"} \
/ user@newhost:/
这里我额外排除了 /swapfile,swap文件跟具体内存状态有关,迁移后要重新创建,复制过来不仅没意义,还可能因为物理地址不同导致问题。
第二步,等业务或日常使用停止后,在维护窗口内再次执行同样的命令,做增量同步。因为第一次全量同步已经把绝大部分数据搬过去了,第二次增量同步只需要传变化的部分,通常几分钟内完成。这个窗口越短,切换时丢失的数据越少。
第三步,在新机器上更新引导和系统配置。关键是修改 /etc/fstab 里的UUID。如果新旧机器分区结构不同,比如旧机器只有根分区,新机器你给home独立分了区,或者交换分区路径变了,都需要重新编辑fstab。我习惯用UUID而不是 /dev/sda1 这种设备名来标识分区,因为设备名在重启后可能变化,UUID是稳定的。
查看分区UUID的命令是 blkid。迁移后在新机器上执行:
bash复制sudo blkid
然后根据输出编辑 /etc/fstab。改完之后先不要直接重启,用下面的命令挂载验证:
bash复制sudo mount -a
没有任何输出就是挂载正常。如果报错,说明fstab里有路径错误或UUID不对,先解决再重启,不然很容易卡在启动阶段进入initramfs交互界面。
最后,确认新机器的网络配置、主机名、SSH Host Key。我遇到过迁移后SSH登录时提示“REMOTE HOST IDENTIFICATION HAS CHANGED”,那是因为新旧机器的SSH主机密钥不同,客户端记住了旧的。这种情况在客户端执行 ssh-keygen -R 目标IP 清除旧记录,重启SSH服务后再登录。
3.3 方案三:整盘克隆与换盘迁移(dd + 分区调整)
整盘克隆最适合的场景是:老硬盘有坏道风险或容量不够,你要把它完整挪到一块新盘上,不想重装系统、不想丢任何数据。
我实测过一个比较典型的操作:把一块256GB的系统盘迁到512GB的新SSD。流程是这样的。
先关机,把新盘接到同一个机器上(可以用USB硬盘盒,也可以直接SATA口),然后从Live USB启动。启动后先确认两块盘的设备名:
bash复制lsblk
假设源盘是 /dev/sda,目标盘是 /dev/sdb。执行克隆:
bash复制sudo dd if=/dev/sda of=/dev/sdb bs=64M conv=fsync status=progress
256GB的盘,按100MB/s以上的写入速度算,大约40分钟到1小时跑完。跑完后,目标盘的容量虽然也显示成256GB逻辑大小,但物理上它是512GB。这时候用 growpart 扩展最后一个分区,再用 resize2fs 扩展文件系统:
bash复制sudo growpart /dev/sdb 2
sudo resize2fs /dev/sdb2
这里的数字2要看你的根分区编号是什么,别一看我写2就照抄。先 lsblk 确认根分区是第几个分区,再去操作。
做完之后,建议把旧盘拔掉,用新盘单独启动一次。如果机器能正常进入系统,再重新插回旧盘当数据盘,格式化之前记得确认新盘启动没问题,否则你把旧盘清了就真回不去了。
用 dd 全盘克隆还会遇到一个困扰很多人的问题:UUID相同。因为 dd 是一比一复制,目标盘的每个分区UUID都和源盘一模一样。如果旧盘和新盘同时在系统里,或者你有多个备份盘,系统可能会因为UUID冲突而挂载错分区。解决方法是克隆后用 tune2fs 给新盘的分区重新生成UUID:
bash复制sudo tune2fs -U random /dev/sdb2
Swap分区如果也有UUID,用 swapoff 停掉后重新 mkswap 生成新的。这个坑我在一次给虚拟机扩容时踩过,恢复后莫名其妙挂载错设备,排查半天才发现是UUID冲突。
3.4 恢复启动引导:Grub重装三步走
很多人在“数据恢复成功但启动不了”这个环节崩溃。文件全部恢复了,但开机直接黑屏或者跳进grub rescue界面。根本原因一般是:MBR/EFI引导记录没有恢复,或者没有在系统里正确安装Grub。
不管你是用 tar 还是 rsync 恢复到新的空白磁盘,都需要重新安装引导装载程序。我的做法是:用Live USB启动,挂载系统分区,然后chroot进去重装Grub。
一个通用的流程:
bash复制sudo mount /dev/sdb2 /mnt/system
sudo mount /dev/sdb1 /mnt/system/boot/efi
sudo mount --bind /dev /mnt/system/dev
sudo mount --bind /proc /mnt/system/proc
sudo mount --bind /sys /mnt/system/sys
sudo chroot /mnt/system
进入chroot环境后,执行:
bash复制grub-install /dev/sdb
update-grub
exit
这里的 /dev/sdb1 和 /dev/sdb2 要替换为你实际的EFI分区和根分区。如果你的系统是BIOS/MBR启动方式(非UEFI),不需要挂载EFI分区,grub-install 直接指向磁盘即可。
这个操作我做过不下十次,最常在两种情况下出问题:一是挂载顺序不对,chroot进去后发现 mount 都挂上了但执行 update-grub 报错找不到os-prober;二是EFI分区没有挂载到 /boot/efi,grub-install 明明执行成功了,但重启后还是找不到系统。所以每一次恢复引导后,我都会再执行一次 efibootmgr -v 来确认启动项存在且顺序正确。
4. 扩展场景与跨环境迁移要点
4.1 虚拟机与容器场景(VMware、Docker)
除了裸机系统,现在很多人把Ubuntu跑在虚拟机里或容器里,这类环境的备份迁移又有自己的特点。
VMware虚拟机备份最简单粗暴的方法就是利用虚拟机自带的快照功能,在关键时间点创建快照。但快照文件膨胀后会影响性能,而且快照不等于备份——如果你把虚拟机文件整体拷贝走,那才是独立于原机的备份。平时管里的虚拟机,我一般用两种方案:平时用快照做快速回滚,升级系统或安装驱动前先在快照里试;需要长周期保存或迁移时,直接把虚拟机目录整体拷贝到另一台宿主机。拷贝过程中虚拟机关机状态拷贝最稳,不开机状态下不会有数据不一致。
Docker场景就更典型了。镜像本身可以 docker save 导出、docker load 导入,容器数据卷则直接是宿主机的目录。我的习惯是把所有持久化数据挂载到宿主机的一个统一目录下,比如 /data/docker,然后备份这个目录即可。一种在我用方案:
bash复制docker save nginx:latest | gzip > nginx_image.tar.gz
结合系统级的 rsync 备份 /data/docker 目录,基本就能覆盖容器所有重要数据。
4.2 数据库与复杂应用的迁移预检
如果你迁移的Ubuntu系统上跑着MySQL、PostgreSQL这类数据库,直接对数据目录做文件级复制是非常危险的。数据库的底层文件在运行时会频繁变化,二进制日志、WAL日志都在实时写入,你贸然复制,可能得到一份“缺胳膊少腿”的数据。
正确的思路是:先用数据库原生工具做逻辑备份或物理备份到一致性快照。比如MySQL用 mysqldump 或 XtraBackup,PostgreSQL用 pg_dump 或 pg_basebackup。待数据库停机或进入备份模式后,再做文件复制。
我已经不止一次遇到有人问“为什么我rsync了mysql的数据目录,启动后数据库就一直报错”,十有八九是因为复制时mysql还在运行,数据文件处于不一致状态。这种问题很隐蔽,因为在复制的时候你根本看不出来异常。
数据库迁移后,还要检查字符集、时区、认证方式这些配置。比如MySQL的 my.cnf 里如果写死了 datadir 路径,换机器后路径变了启动就会失败;PostgreSQL的 pg_hba.conf 里如果有基于IP的认证信息,迁移后也要跟着改。
4.3 跨架构与国产化平台迁移的注意点
现在越来越多人在讨论从x86迁移到ARM架构,或者从传统Linux迁移到国产平台,比如银河麒麟、统信UOS等。这类迁移的核心矛盾是:源码兼容和二进制兼容。
.so 共享库从x86往ARM上迁,经常会出现“cannot execute binary file”或者“wrong ELF class”的报错,本质是架构不匹配,这两种架构的机器码不通用,必须拿到ARM版本的库或源码重新编译。Python虚拟环境迁移同样受影响,site-packages 下面很多带C扩展的包,换架构后不能直接用,需要在目标平台 pip install --no-cache-dir 重新从源码构建。
数据库迁移和国产平台结合时也有坑。我在福昕麒麟上用达梦数据库时发现,达梦的JDBC驱动对不同CPU架构的支持情况有所不同,迁移后连接不上,很多时候是驱动版本和架构不匹配。建议迁移前先到目标平台上跑一遍完整的驱动兼容测试。
应对跨架构迁移,我的建议是:不要想着一步“搬过去”,先在目标平台建一个最小可用环境,把依赖一个个装起来,验证一个过掉一个。很多历史悠久的老项目依赖链复杂,直接整体迁移很容易“按下葫芦浮起瓢”,拆开来逐个击破成功率反而高很多。
4.4 从WSL到虚拟机:另类迁移路线
Windows用户常用WSL跑Ubuntu,这里也会遇到迁移问题。WSL的发行版本质是根文件系统加少量元数据,整体迁移其实比物理机简单。
我在WSL里做过一次迁移,思路是先干净地关闭WSL环境,然后导出为tar归档:
bash复制wsl --export Ubuntu-22.04 D:\backup\ubuntu-wsl.tar
需要恢复时,用:
bash复制wsl --import Ubuntu-22.04 D:\ubuntu-new D:\backup\ubuntu-wsl.tar
WSL里的文件大多在 /home/ 下,如果只是想备份数据,在WSL内部直接 tar -czf backup.tar.gz /home 也行。我更推荐这种方式,因为导出整个WSL镜像文件会包含所有发行版内组件,体积非常大,但好处是恢复后所有软件和环境都在。
反之,如果你想从WSL迁回真正的虚拟机,由于WSL的根文件系统本质是一个ext4虚拟磁盘文件,可以通过 wsl --export 然后是 wsl --import 再导出根文件系统,然后用rsync方式同步到虚拟机。这个路线稍微绕,但实际验证过是可行的。核心要领就是:先转成标准的tar归档,再利用常规的恢复流程。
另外,很多人在WSL里折腾字体和终端配色。如果你从macOS转过来,想把macOS的字体渲染体验带到WSL下的终端,我的经验是:安装开源字体方案后,终端工具(如Windows Terminal、VS Code)里把字体设置为等宽字体,再把反锯齿和连字效果都打开,渲染效果接近macOS原生体验。这些设置都保存在用户配置文件里,迁移WSL环境时记得把相关配置文件一并带过去,不然新环境里字体渲染差别很大。
5. 常见问题与排查技巧实录
5.1 备份过程中常见的坑
问题1:tar 备份时提示“file changed as we read it”
这个警告是正常的。它表示在读取文件的过程中,文件内容发生了变化,一般是因为有服务在运行,比如日志轮转或数据库在写入。如果你的备份目标是系统盘且没有停机,这个警告多少会有一点。要尽量避免,应该在维护窗口、停服状态下执行备份,尤其数据库要先停掉或执行 FLUSH TABLES WITH READ LOCK。
问题2:rsync 远程备份连不上SSH
先确认目标机器的SSH服务正常运行 systemctl status ssh,然后确认网络能通,再检查防火墙 ufw status。我用过最多的情况是被防火墙挡住。另外,如果使用非22端口,rsync 命令要写 -e "ssh -p 端口号",不写的话默认连22端口,怎么都连不上。
问题3:dd 备份目标盘空间不足
dd 不会检查目标盘是否足够大,它只会写到失败为止。所以在执行 dd 前一定要用 lsblk 确认目标盘容量大于或等于源盘。相比之下,ddrescue 在遇到空间不足时会比较友好地停止。所以在做全盘备份前,我一般先查看两块盘的容量:
bash复制lsblk -o NAME,SIZE,MODEL
源盘块容量略大于目标盘时,先想办法把源盘上看不到但实际占用的空间缩一缩,或者直接放弃dd改用rsync迁移,不然容易做无用功。
问题4:tar 恢复后启动陷入 initramfs 提示“UUID does not exist”
这个问题我遇到过太多次了。根本原因就是 /etc/fstab 里的UUID与实际磁盘分区不匹配。可能是恢复了之前备份的文件,里面的fstab还是旧盘的UUID,而新盘或新分区已经重新格式化生成了新UUID。解决办法是进Live环境,挂载根分区,修改fstab里的UUID:
bash复制sudo mount /dev/sdb2 /mnt/system
nano /mnt/system/etc/fstab
对照 blkid 输出,把根分区、home分区、swap分区的UUID改成实际的,保存后退出重启。
5.2 恢复后常见的疑难杂症排查表
下表是我在多次备份恢复实操作后,整理出的高频异常及处理办法,可以直接对照使用。
| 现象 | 可能原因 | 处理办法 |
|---|---|---|
| 恢复后开机卡在grub rescue | 引导文件缺失或未安装Grub | Live USB启动,chroot后重新执行grub-install和update-grub |
| 启动进入initramfs并提示UUID不存在 | fstab里的UUID与分区不匹配 | 修改fstab,用blkid的结果逐一校正 |
| 网络不通、网卡名变成预测性名称 | 系统迁移后udev规则变化 | 检查网络管理器连接配置;systemd预测性接口命名需确认配置文件 |
| SSH登录提示host key冲突 | 新旧机器SSH主机密钥不同 | 清除客户端known_hosts里对应的旧记录 |
| 桌面环境字体模糊或没有输入法 | 用户配置丢失 | 检查home目录是否恢复完整,缺失时重新安装输入法并拷贝当前用户的配置 |
| 软件源失效、apt update报错 | 系统版本与源不匹配 | 编辑/etc/apt/sources.list及/etc/apt/sources.list.d/下的源配置,替换为匹配当前版本的源 |
| Docker容器启动失败 | 数据卷路径或权限不对 | 检查/data/docker等数据卷目录是否恢复,容器权限是否正常,必要时重建容器但挂载原数据卷 |
5.3 最后的防护底线:定期自动备份
实操中,“有备份”和“定时备份”是两回事。一台机器如果全靠手动想起来才备份,那等到系统崩溃时,你手里往往是最旧的那份备份。我的习惯是设置cron任务做周期性rsync同步。
一个简单的备份脚本:
bash复制#!/bin/bash
# 系统数据增量同步到备份盘
rsync -aAXv --delete \
--exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found","/swapfile"} \
/ /mnt/backup/rsync/
# 记录备份完成时间
echo "$(date): backup done" >> /var/log/backup.log
把脚本放到 /usr/local/bin/backup.sh,加上可执行权限:
bash复制sudo chmod +x /usr/local/bin/backup.sh
然后编辑crontab:
bash复制sudo crontab -e
# 每天凌晨2点执行
0 2 * * * /usr/local/bin/backup.sh
定时的意义在于,让备份成为系统的一个“呼吸动作”,而不是“灾难之后的反省”。真正等到数据没了才想起来,那才是真的来不及。
6. 备份策略的经验总结与建议
在我的观念里,一个合格的备份策略需要满足三个条件:能恢复、足够新、可自动化。能恢复意味着你必须演练过恢复流程,不要等到灾难哪天真的来了才第一次尝试从备份里捞数据;足够新意味着备份间隔不能超出你可接受的数据丢失时间窗口;可自动化则保证你不会因为“这周太忙忘了备份”而把整个方案废掉。
个人比较推荐“3-2-1”备份原则:核心数据保留三份,存放在两种不同的存储介质上,其中至少一份放在异地(比如对象存储、另一个机房或朋友的机器上)。这个原则虽然源自企业数据保护领域,但对个人用户同样适用。我自己在家里就是这么运作的:系统盘里有原始数据,外接移动硬盘每天定时rsync一份,重要的不可再生资料(照片、密码库、开发项目)还会定期tarball后放到云存储上。
至于用哪个工具备份,看似是技术选型问题,本质上是风险偏好问题。图省事,就用rsync搭个定时同步,平时基本感觉不到它的存在;要保留历史快照,就定期tar归档,按日期命名妥善保存;要整体迁移或克隆系统,dd派上用场;跨架构迁移则依赖源码编译和配置迁移。工具是死的,组合是活的。
最后分享一个小技巧:备份完成后,别急着拔盘走人。花两分钟打开备份目录,随机抽几个文件打开看看内容,或者直接在Live环境里把备份恢复到虚拟机里跑一遍。这个过程看起来多花了时间,但真正遇到“备份打不开”的那天,你会感激自己当初的“多此一举”。
