Linux 系统备份与恢复策略

3次阅读

rsync增量备份快但易漏权限和硬链接,需加-ah等参数;dd恢复gpt+uefi需校验分区表和esp;systemd服务恢复后须daemon-reload或reenable;备份命名应避免依赖date+%s,推荐latest文件机制。

Linux 系统备份与恢复策略

rsync 增量备份为什么比 tar 全量快,但容易漏掉权限或硬链接

因为 rsync 默认只同步文件内容和修改时间,不强制保留所有元数据。实际用时少,但恢复后可能发现 chmod 失效、ls -l 显示用户为数字 ID、或者硬链接变成独立副本。

  • 必须加 -a(等价于 -rlptgoD),尤其不能省略 -p(权限)、-o(属主)、-g(属组);-H 要显式加上才能保硬链接
  • 如果目标是跨文件系统备份(比如从 ext4 备到 btrfs),-H 有时仍会失效,此时得用 --hard-links 配合 --one-file-system 控制范围
  • rsync -aH --delete /source/ /backup/ 是常见组合,注意末尾斜杠:/source/ 表示同步目录内容,/source 不带斜杠会多嵌一层目录

dd 全盘镜像恢复失败,常见于 GPT 分区 + UEFI 启动场景

dd 确实能做位对位复制,但 GPT 分区表含两份备份(头部 + 末尾),且 EFI 系统分区(ESP)需 FAT32 格式、有特定启动文件结构。dd 恢复后常出现“no bootable device”不是因为没写完,而是 ESP 里 efi/boot/bootx64.efi 路径或权限不对,或 GPT 备份头未更新。

  • 恢复前先用 gdisk -l /dev/sdX 确认源盘 GPT 结构是否完整;恢复后立即运行 gdisk /dev/sdX → 输入 rv 验证,再 w 写回备份头
  • ESP 分区挂载后检查:ls -l /mnt/esp/EFI/ubuntu/(或对应发行版目录),确保 bootx64.efi 存在且非 0 字节;FAT32 不认 unix 权限,但 cp 时别用 -p
  • dd if=image.img of=/dev/sdX bs=4M status=progress 是基础命令,但别用 conv=notrunc 恢复到比原镜像大的盘——GPT 末尾备份位置会错位

systemd 服务配置被备份覆盖后无法启用

用户手动改过 /etc/systemd/system/myservice.service,但用 rsync -a 从旧备份恢复后,systemctl enable myserviceFailed to enable unit: Unit myservice.service does not exist。问题不在文件丢失,而在 systemd 的运行时缓存和符号链接机制。

  • 恢复配置文件后,必须执行 systemctl daemon-reload,否则 systemd 仍用旧的 unit 缓存
  • 若该服务曾被 enable 过,/etc/systemd/system/multi-user.target.wants/ 下应有指向它的软链;rsync -a 默认不复制软链目标,只复制链本身——所以恢复后链接可能指向不存在路径
  • 稳妥做法:恢复后运行 systemctl reenable myservice(先 disable 再 enable),或手动检查并重建软链:ln -sf /etc/systemd/system/myservice.service /etc/systemd/system/multi-user.target.wants/myservice.service

备份脚本里用 date +%s 生成文件名,恢复时却找不到最新备份

看似稳妥的时间戳命名,在跨时区服务器、NTP 同步异常、或 cron 使用不同 shell 环境时,date +%s 可能产出重复值或乱序。更麻烦的是,ls -t 按 mtime 排序,而备份文件的 mtime 是写入完成时间,不是命名里的时间戳。

  • 别依赖 ls -t | head -1 找最新备份;改用 ls *.tar.gz | sort -V | tail -1(按版本号逻辑排序),或直接解析文件名:ls backup_*.tar.gz | sed 's/backup_([0-9]+).tar.gz/1/' | sort -n | tail -1
  • 在备份脚本开头加 export TZ=UTC,避免本地时区干扰;写入前用 sync 确保时间戳写入磁盘
  • 更可靠的做法:每次备份后写一个 LATEST 文件,内容就是本次文件名,恢复时直接读它——简单,无歧义

真正麻烦的不是备份动作本身,而是元数据一致性、路径语义差异、以及工具链之间那些不声不响的默认行为。多一次 ls -l,多一次 file,多一次 systemctl status,比事后重装快得多。

text=ZqhQzanResources