Linux服务器如何制作系统恢复方案?救援模式、备份与启动修复指南

运维做久了都会明白一个道理:服务器迟早会出问题,区别只在于出问题时你是有准备的,还是手忙脚乱的。磁盘写满、误删文件、GRUB 损坏、fstab 写错导致起不来、根密码忘了、系统被误改配置——这些都可能让一台好好的服务器进不了系统。如果事先没有恢复方案,就只能干着急。

这篇文章不讲单一命令,而是教你建立一套完整的"系统恢复能力":一是平时就做好备份和基线,让恢复有据可依;二是掌握救援模式的进入方法和常用修复手段,能在起不来时救回来;三是针对典型故障(引导损坏、挂载失败、误删文件、密码丢失)给出具体处置流程。文中涉及引导、分区、chroot 等高风险操作,每一步都会说明风险和回滚思路,请务必在确认设备名的前提下操作。

读完你应该能:为团队规划出一套可执行的恢复方案,明确"备份什么、怎么进救援、如何修引导、出事谁来操作",把不可控的突发故障变成有预案的常规操作。

一、恢复能力的第一步:备份与基线

真正决定恢复效率的,不是出事时手有多快,而是平时备份做得有多好。没有备份,救援模式能救的也只是"系统能起来",丢的数据救不回来。

需要备份的东西分几类:

类型 内容 备份方式 恢复优先级
业务数据 数据库、上传文件、业务目录 逻辑备份 + 物理快照 最高
配置 /etc 下的关键配置 版本管理或定期打包 高
系统基线 已装包列表、系统信息 脚本导出 中
引导信息 分区表、GRUB 配置、fstab 文本导出 高(救机用)
密钥证书 SSH 密钥、SSL 证书 离线加密保存 高

导出系统基线(救机或重建时非常有用):

# 已安装包列表(用于重建或对比)
# RHEL 系
rpm -qa | sort > /backup/pkglist-$(hostname)-$(date +%F).txt
dnf repolist > /backup/repolist-$(date +%F).txt
# Debian 系
dpkg -l > /backup/pkglist-$(hostname)-$(date +%F).txt
apt-mark showmanual > /backup/manual-pkgs-$(date +%F).txt
dpkg --get-selections > /backup/dpkg-selections-$(date +%F).txt

# 关键系统信息
{
  echo "=== os ==="; cat /etc/os-release
  echo "=== kernel ==="; uname -a
  echo "=== disks ==="; lsblk -f
  echo "=== fstab ==="; cat /etc/fstab
  echo "=== partitions ==="; sudo parted -l 2>/dev/null
  echo "=== network ==="; ip -br a; ip route
  echo "=== enabled services ==="; systemctl list-unit-files --state=enabled
} > /backup/system-info-$(date +%F).txt

# 关键引导/分区信息(救机时的地图)
sudo sfdisk -d /dev/vda > /backup/partition-table-vda-$(date +%F).txt 2>/dev/null
sudo cp /boot/grub2/grub.cfg /backup/grub.cfg.bak 2>/dev/null   # RHEL 系
sudo cp /boot/grub/grub.cfg /backup/grub.cfg.bak 2>/dev/null    # Debian 系
sudo cp /etc/fstab /backup/fstab.bak

配置备份(/etc 是重灾区,改前必备份):

# 打包 /etc(排除大文件和敏感内容按需处理)
sudo tar czf /backup/etc-$(date +%F).tar.gz /etc \
  --exclude=/etc/mtab --exclude=/etc/udev/rules.d/70-persistent*

# 用 git 管理 /etc 是更规范的做法(另建仓库,不放在 /etc 里)

数据备份要点:

  • 数据库不要直接拷数据文件(热备可能不一致),用 mysqldump/pg_dump 或物理备份工具(xtrabackup 等)。
  • 备份要异地/异盘存放,别和业务数据放同一块盘。
  • 云主机善用快照,但快照不能替代应用级备份(数据库一致性、跨盘一致性)。
  • 定期验证恢复——只备份不演练,等于没备份。

二、进入救援模式:三条路

系统起不来时,先要能进得去。根据情况有几种途径。

途径一:GRUB 菜单进单用户 / 救援内核参数

适用于系统还能引导到 GRUB,但启动过程中卡住(比如 fstab 写错、服务卡死)。

# 开机时在 GRUB 菜单选中要启动的内核,按 e 编辑
# 找到以 linux 开头的那一行,在行尾追加:
systemd.unit=rescue.target      # 救援模式,挂载文件系统,单用户,需 root 密码
# 或
systemd.unit=emergency.target   # 紧急模式,最小挂载,通常根为只读
# 或
init=/bin/bash                 # 直接进 bash,文件系统可能只读,需手动 remount
# 或(旧内核参数,用于跳过 fsck / 挂载)
single                          # 单用户
# 改完后按 Ctrl+X 或 F10 启动

进入后如果根文件系统是只读的,先重挂为可写:

mount -o remount,rw /

途径二:云控制台的 VNC / 串口控制台

云主机的"带外"通道,不需要 SSH、不需要系统能正常启动到网络阶段。这是远程救机最重要的一条命脉,务必平时就确认能用、知道在哪打开。

途径三:安装介质 / 救援盘进入救援环境

系统完全无法引导(GRUB 损坏、分区表损坏)时,用同发行版的安装 ISO 或专门的救援盘启动,选择"Rescue"模式,进入一个临时的 Linux 环境,再把目标系统的根分区挂载起来修复。

# 救援环境里通常需要手动挂载原系统
lsblk                                   # 找到原系统的根分区,例如 /dev/vda2
mkdir -p /mnt/sysroot
mount /dev/vda2 /mnt/sysroot
# 如果 /boot 是独立分区
mount /dev/vda1 /mnt/sysroot/boot
# 绑定必要的虚拟文件系统
for d in dev proc sys run; do mount --bind /$d /mnt/sysroot/$d; done
# 进入原系统
chroot /mnt/sysroot
# ...在 chroot 内做修复...
exit
# 卸载(注意顺序)
umount -R /mnt/sysroot

风险提示:救援环境里你面对的是裸磁盘,grub-install、mkfs、dd 等命令一旦设备名写错,可能覆盖正常分区或数据盘。执行前用 lsblk -f 反复确认,最好先在另一台机器上演练。

三、修复典型故障

故障一:GRUB 引导损坏,开机直接进 GRUB 命令行

现象:开机出现 grub> 提示符,或报 error: unknown filesystem、no such partition。

# 在 grub> 提示符下手工引导(临时进入系统用)
grub> ls                    # 列出磁盘和分区 (hd0) (hd0,gpt1) ...
grub> ls (hd0,gpt2)/        # 探测哪个分区是 /boot 或根
grub> set root=(hd0,gpt2)
grub> linux /vmlinuz-<版本> root=/dev/vda2 ro
grub> initrd /initramfs-<版本>.img      # RHEL 系;Debian 是 /initrd.img-<版本>
grub> boot

进入系统后重建 GRUB:

# RHEL / Rocky / Alma(BIOS 引导)
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
sudo grub2-install /dev/vda

# RHEL 系(UEFI 引导)
sudo grub2-mkconfig -o /boot/efi/EFI/rocky/grub.cfg   # 路径按发行版
sudo grub2-install --target=x86_64-efi --efi-directory=/boot/efi

# Debian / Ubuntu
sudo update-grub
sudo grub-install /dev/vda
# UEFI:
sudo grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=ubuntu

故障二:fstab 写错,开机进紧急模式

现象:启动到一半提示 emergency mode,或 Failed to mount /data。

# 进入紧急模式后根通常只读
mount -o remount,rw /

# 编辑 fstab,注释掉有问题的行(行首加 #)
vi /etc/fstab
# 不确定是哪一行出错,先全部注释掉,保证能进系统,再逐行恢复
# 或者直接恢复备份
cp /etc/fstab.bak /etc/fstab

# 验证后重启
reboot

这也再次说明:改 fstab 前备份、改后用 mount -a 验证,是必须养成的习惯。

故障三:根分区写满导致服务全挂

磁盘满会让数据库、日志、甚至系统服务异常,有时表现为"什么都起不来"。

# 先找哪个目录/文件占空间
df -h
df -i                    # 顺便看 inode 是否耗尽(大量小文件常见)
du -sh /var/* 2>/dev/null | sort -h | tail
du -sh /var/log/* | sort -h | tail

# 找大文件
find / -xdev -type f -size +1G -exec ls -lh {} \; 2>/dev/null | head

# 清日志(用 truncate,别直接 rm 正在写的文件)
sudo truncate -s 0 /var/log/huge.log
# 清理 journal(保留最近 200M)
sudo journalctl --vacuum-size=200M
# 清理旧的包缓存
sudo dnf clean all 2>/dev/null
sudo apt clean 2>/dev/null
# 找出被删除但仍被进程占着的文件(空间没释放的经典原因)
sudo lsof +L1 2>/dev/null | head
# 处置:重启对应进程或服务,让描述符释放

风险提示:清理前确认文件可以删。truncate 正在被写的日志文件是安全的(进程句柄还在),直接 rm 则可能让进程继续写到"幽灵文件"上、空间仍不释放。

故障四:误删系统文件 / 配置被改坏

  • 误删的配置文件(/etc 下):从备份恢复,或用包管理器重装对应包来还原默认文件。
  • 误删的系统二进制/库:用包管理器重装,dnf reinstall <包> / apt install --reinstall <包>。
  • 误删的用户数据:如果有备份就恢复;没有备份则看该文件是否还被进程打开(lsof | grep deleted),能救则救,否则只能承认损失——这就是备份重要性的最好证明。

故障五:忘记 root 密码

在有物理/控制台访问权限的前提下,可以重置。

# 方法:进入 GRUB,编辑内核行,在行尾加:
rw init=/bin/bash
# 或 rd.break(RHEL 系,会在 initramfs 阶段停下)
将 ro 改成 rw,并加 init=/bin/bash,然后启动

# 进入 bash 后
passwd root                # 修改密码
# 若是 SELinux 开启的系统(RHEL 系),需要重打标签,否则可能登录异常
touch /.autorelabel
exec /sbin/init            # 或 reboot -f

这说明:服务器不设 root 密码保护是不可接受的物理安全风险——任何能接触控制台的人都能重置密码。BIOS 密码、磁盘加密、机房门禁是配套手段。

四、把恢复能力制度化

零散的技巧不足以支撑可靠运维,最好把恢复能力做成制度。

第一,明确 RTO/RPO。 RTO 是"允许多久恢复"(比如 1 小时),RPO 是"允许多少数据丢失"(比如 15 分钟)。这两个数字决定了备份频率和恢复手段:RPO 要求高就得用增量备份或实时复制;RTO 要求高就得准备热备或快速重建能力。

第二,准备"启动恢复盘"。 备一份和系统同版本的安装 ISO 放在独立位置(比如 U 盘、另一台机器),关键时刻能用来进救援环境。

第三,写清恢复手册。 包括:怎么进控制台、怎么找磁盘、怎么挂载、怎么重建引导、怎么从备份恢复。手册要定期演练,别等真出事才发现步骤是错的。

第四,区分"救系统"和"保数据"。 有时最快的方案不是修复系统(可能耗几小时),而是用备份在干净系统上重建。对容器化/配置管理做得好的环境,重建往往比修更快更可靠。

场景 优先策略 理由
单点服务、可容忍短停机 就地修复(救援模式) 保存现场,恢复快
复杂系统、配置已代码化 重建 + 数据恢复 更可靠,避免残留脏状态
数据是唯一资产 保数据优先,系统可重建 数据不可再生
多地多活 切流量到其他节点 恢复最快

第五,保留"带外通道"。 云主机的 VNC/串口、物理机的 IPMI/iDRAC/iLO 必须在平时就验证可用,并确保值班的人知道怎么用。

常见问题

Q1:救援模式下根分区挂载报错怎么办?
先 lsblk -f 确认分区和文件系统类型,确认设备名没错。若是文件系统损坏,先用 e2fsck -f /dev/vda2(ext4,需先 umount)或 xfs_repair(XFS)修复。对已挂载的盘不要直接 fsck。

Q2:fstab 写错导致起不来,最简单的救法是什么?
进紧急模式或救援环境,mount -o remount,rw / 后编辑 /etc/fstab 注释掉问题行,或恢复备份,重启。养成改前 cp /etc/fstab /etc/fstab.bak 的习惯。

Q3:用云主机时,救援模式怎么进?
优先用云控制台的 VNC/串口控制台,在 GRUB 里加 systemd.unit=rescue.target 或 init=/bin/bash,或引导到旧内核。也可以把系统盘挂到另一台机器上修复,云厂商通常有"挂载到救援实例"的功能。

Q4:重置 root 密码后 RHEL 系统登录异常?
多半是 SELinux 标签问题。在救援 bash 里 touch /.autorelabel 让系统下次启动重打标签,然后重启。

Q5:备份多久做一次、保留多久?
取决于 RTO/RPO。常见做法是数据库每日全备 + 更频繁的增量/binlog,配置进版本库每次改动即提交,系统镜像定期快照。保留策略按合规和成本定,但一定要有异地副本并定期演练恢复。

总结

  • 恢复能力 = 平时备份 + 救援手段 + 预案手册,三样缺一不可;没有备份,救援模式也只能救"系统能起来",救不回数据。
  • 备份要覆盖业务数据、/etc 配置、系统基线(包列表、分区表、fstab、GRUB)三类,异地存放,并定期演练恢复验证。
  • 起不来时先想办法进入:GRUB 加 systemd.unit=rescue.target、用云控制台 VNC/串口、或用安装介质进救援环境后 chroot 修复。
  • 典型故障各有套路:引导损坏重建 GRUB、fstab 写错注释并恢复备份、磁盘写满用 truncate/vacuum 清理、误删文件靠重装包或备份恢复。
  • 把恢复制度化:明确 RTO/RPO、备好恢复盘、写并演练恢复手册、保留带外通道,并在"就地修复"与"干净重建"之间按场景做选择。