Linux虚拟机紧急模式排查与修复全攻略
2026/9/17 9:08:49 网站建设 项目流程

虚拟机跑得好好的,某天早晨启动发现控制台没进图形界面,落在一个黑底白字的提示符上,写着“Welcome to emergency mode!”。很多人在这一步就慌了,以为是虚拟机文件损坏、系统崩溃,甚至直接删了重装。实际上紧急模式是 Linux 在系统初始化失败时主动降级出来的“安全屋”,目的就是给你一个最小环境去排除问题。这篇文章就围绕这套流程展开:从紧急模式为什么会出现,到进去之后怎么定位、怎么修、怎么退出,再到日常怎么避免再犯,全部按照我在 VMware 和 VirtualBox 上排障的真实路径来写,适合刚接触 Linux 虚拟机的读者,也适合被这个问题反复折磨过的老用户参考。

1. 紧急模式不是死机:先搞懂引导流程里的“安全阀”

1.1 emergency.target 和 rescue.target 到底有什么区别

很多教程把紧急模式、救援模式、单用户模式混着说,真到排查时容易走偏。这里先明确概念。在 systemd 体系的 Linux 发行版里,系统启动时会按照依赖关系拉起一系列 target,你可以把 target 理解成“一组服务打包在一起的状态”。

救援模式对应rescue.target,它会把根文件系统挂载成读写,然后启动一个最小化的系统环境,基础服务尽量带上,适合修复系统文件和重装引导。紧急模式对应emergency.target,它是比救援模式更“裸”的状态,根文件系统默认以只读方式挂载,此时很多服务都没起来,就等你手动干预。

为什么启动会落到 emergency.target?最典型的原因是 systemd 在启动过程中发现某个“必须挂载成功”的文件系统挂载失败。systemd 的设计逻辑是:你有一个挂在/etc/fstab里的启动项,它如果失败,系统不能当作没看见继续往上跑,否则后续依赖这个目录的服务都会出现问题。所以它干脆拦住所有依赖,把你送到一个能“看见问题、去修问题”的提示符前。

1.2 从虚拟机按下电源到 emergency 提示符的完整链路

按电源键之后,虚拟机内部大致走这么一条链:BIOS/UEFI 自检 → 引导加载器 GRUB → 内核压缩包加载 → systemd 作为第一个进程启动 → 开始执行各种 target 和 service。

systemd-fstab-generator会把/etc/fstab中的条目转换成对应的.mount单元,这些 mount 单元又被归到local-fs.target。如果你的 fstab 里有一条配置指向了一个不存在的 UUID,或者磁盘设备没准备好,systemd 在尝试挂载时会超时或直接报错。这个失败会一路向上传递,最终导致local-fs.target无法达成,systemd 只能退而求其次,进入emergency.target

有一个非常容易误判的点:很多用户以为是因为上次“非正常关机”才进入紧急模式,其实非正常关机引发的本质问题是文件系统脏标记(dirty flag)。虚拟机关机时正在写缓存,突然断电或强制停止,文件系统元数据没及时 flush,下次启动时系统检查发现不一致,挂载失败。这里是两层问题叠在一起:一是文件系统本身有损坏,二是挂载行为失败触发了紧急模式。后面排查的时候,这两点都要覆盖到。

2. 我实际踩过的触发场景:没有一次是“没理由”的

2.1 “上次意外关机”是最常见的元凶

在 VMware Workstation 里,如果虚拟机非正常退出,下次列表里会看到“此虚拟机可能已被移动或复制”,再点开虚拟机电源时,内部 Linux 大概率会进入紧急模式。我的第一台 Ubuntu Server 虚拟机就是因为宿主机断电,启动后直接掉进 emergency。

这背后的因果并不复杂:VMware 的虚拟磁盘,无论是 vmdk 还是 vdi,底层都是一个文件,宿主机断电时这个文件里的缓存数据不一定完整。Linux 的 ext4/xfs 文件系统在写入过程中如果被硬生生截断,磁盘上的 journal(日志)可能缺失,mount 时无法确认一致性,要么挂载成只读,要么直接报错。极端情况下,fsck还会发现 inode 和 block bitmap 对不上,要求你手动修复。

2.2 手改 fstab 和扩容虚拟磁盘带来的连环坑

这个场景在论坛里出现的频率仅次于意外关机。典型操作路径是:先在 VMware 的设置里把虚拟磁盘从 20G 扩到 40G,然后在 Linux 里用fdisk或者growpart扩展分区,最后为了让新空间生效,手动往/etc/fstab添加了一个新分区的挂载条目。

问题出在哪里?新分区如果是用mkfs.ext4初始化的,它的 UUID 和你 fstab 里写的那个 UUID 对不上;或者你顺手写的是/dev/sda3这种设备名,这个设备名在某些场景下重启后会变化。一旦 fstab 里有任何一条解析失败或挂载失败,紧急模式就像值班保安一样把你拦下来。

我印象很深的一次是:我添加了一个/data挂载点,当时用blkid查到了 UUID,但复制的时候多复制了一个空格,或者少写了一个字符,系统启动直接进了 emergency。这种问题特别打击信心,因为其他配置完全没动过。

2.3 宿主机磁盘写满,虚拟磁盘 I/O 报错引发启动中断

还有一种隐蔽的情况。虚拟机本身没问题,但宿主机磁盘满了,VMware 无法继续向 vmdk 文件写入新数据,虚拟机内部会感受到持续性 I/O 错误。此时如果虚拟机正在执行定期写入,可能会出现分页错误甚至文件系统只读重挂载。

更麻烦的是,快照会让这个问题放大。VMware 的快照机制会生成 delta 文件,快照打得多了,snapshot文件占用的空间可能比原始 vmdk 还大。如果宿主机的磁盘空间被这些快照文件蚕食,虚拟机的写入一旦失败,系统启动时做日志回放也可能失败,最后表现为一个毫无头绪的 emergency 模式。

虚拟机领域的排查有一条铁律:先把问题摘干净。所谓摘干净,就是把宿主机的磁盘空间、内存资源、虚拟化服务日志都检查一遍,再进入虚拟机内部去折腾 fstab。

3. 在紧急模式提示符下逐层剥开问题:诊断实操记录

3.1 先拿回 root 权限:密码登录和输入法陷阱

紧急模式默认会弹出一个提示,要求输入 root 密码登录。这是最容易卡住新手的环节,因为很多人在安装 Linux 虚拟机时根本没有设置 root 密码,系统提示时想当然地输入当前用户的密码,结果一直认证失败。

如果你还记得 root 密码,直接输入即可;如果不记得,需要在 GRUB 引导菜单处做处理。具体方法是在 GRUB 界面选中内核行,按e编辑启动参数,找到linux开头那一行,在末尾追加rd.break(CentOS/RHEL 系)或init=/bin/bash(Ubuntu 系可以临时改),然后按Ctrl-x启动,进入环境后挂载 sysroot 修改 root 密码。这个步骤比较繁琐,但是虚拟机环境坏了无法正常登录时的兜底方案。

这里的实际操作逻辑是:紧急模式把你送到一个类似“带网络功能的最小系统”里,但不一定所有分区都挂载。如果你用lsblk查看,会看到根分区可能处于只读状态或者根本没挂载。先确认自己的身份是 root,再开始诊断。

3.2 用 journalctl 和 systemctl 快速定位失败源

输入 root 密码进入提示符后,第一件事不是盲目去改文件,而是确认到底哪个环节出了问题。优先执行这几条命令:

journalctl -xb systemctl --failed systemctl status local-fs.target

journalctl -xb会把本次启动日志和 systemd 额外信息都打出来,信息量很大,建议配合grep过滤。比如:

journalctl -b -p err journalctl -b -u dev-sda2.device journalctl -b | grep -i "Failed to mount"

systemctl --failed更直接,它会把当前启动中失败的系统单元列出来,形成一张清单。我在几次排障中看到的典型的失败单元包括:

UNIT LOAD ACTIVE SUB DESCRIPTION dev-disk-by\\x2duuid... loaded failed failed /data

看到这个信息后,方向基本就锁定到了 fstab 或分区的问题上。

3.3 mount -a 和 findmnt:手动验证 fstab 是否“能跑通”

知道问题大体上出在挂载环节后,可以手动执行一条很有价值的验证命令:

mount -a

这条命令的作用是重新读取/etc/fstab,并尝试把里面所有条目挂载一遍。如果某一条配置有误,系统会立刻打印错误信息,比如:

mount: /data: special device UUID=xxxx-xxxx-xxxx does not exist.

看到这条消息,问题定位就完成了九成。你也可以用findmnt -s来查看 fstab 解析出来的挂载树,它会告诉你每一行挂载配置解析后的设备源、挂载点和文件系统类型。

如果mount -a显示一切正常,但journalctl里明明有失败记录,那就可能是挂载顺序或依赖条件的问题,比如网络文件系统需要在网络就绪后才能挂载,但相关配置顺序不对。

4. fstab 修复现场:从 UUID 对不齐到目录缺失的完整处理

4.1 fstab 每一列的含义,以及最容易写错的地方

/etc/fstab是 Linux 文件系统挂载的核心配置文件,每一行包含 6 列,含义分别如下:

列号含义示例常见错误
1设备源/dev/sda1UUID=...手动填写设备名导致重启后变化
2挂载点//data目录不存在但未创建
3文件系统类型ext4xfsvfat与分区实际格式不一致
4挂载选项defaultsnoatime选项拼写错误
5是否 dump 备份01强行填 1 但没有 dump 顾虑不大
6fsck 检查顺序/1,其他填2,不需要检查填0所有分区填 0 导致根分区未检查

最容易出错的集中在第一列和第三列。很多新手习惯写/dev/sda1,这个写法在虚拟机里一般没问题,但一旦磁盘顺序因添加虚拟磁盘发生变化,sda 可能变成 sdb,整个 fstab 就挂了。正确的做法是用blkid查 UUID,然后写入配置。

4.2 修复核心动作:用 blkid 核对 UUID 并注释或替换故障行

进入紧急模式后,第一步先查看当前磁盘的真实标识:

blkid

输出会列出所有分区的 UUID、类型和标签。你把 fstab 里写的 UUID 和这个输出逐一比对,凡是blkid里查不到的 UUID,对应行就是你启动失败的元凶。

处理方法有两种。如果那个挂载点确实没用了,直接在该行前面加#注释掉:

# UUID=不存在的uuid /data ext4 defaults 0 2

如果挂载点仍然需要,就用blkid查到的正确 UUID 覆盖原来的错误值,然后用mount -a验证:

mount -a && echo "OK"

另外注意,挂载目录本身必须存在。如果 fstab 里写了挂载点/data,但/data目录不存在,挂载一样会失败。在紧急模式下创建目录再验证:

mkdir -p /data mount -a

4.3 当问题不在 fstab:fsck 修复虚拟磁盘文件系统

如果你的blkid输出里 UUID 都对得上,mount -a也能执行,但问题依旧,那么要考虑文件系统本身是否需要修复。

文件系统修复要在磁盘未挂载的状态下进行。紧急模式下,如果目标分区还没有挂载,可以直接执行:

fsck /dev/sda1

如果系统提示文件系统类型为 ext4,也可以用:

fsck.ext4 -fy /dev/sda1

这里的-f表示强制检查,-y表示所有交互确认都自动回答 yes。在虚拟磁盘上执行 fsck 通常耗时较长,特别是磁盘文件本身巨大、快照份数多的时候,请给足耐心。修复完成后,用reboot重启,看能否正常进入系统。

有一个重要的判断点:fsck只能修复文件系统层面的日志错误,不能修复硬件坏道。虚拟机里没有真实坏道,但 vmdk 文件如果被压缩工具损坏,读出来可能是一连串 I/O mismatch。如果 fsck 反复报告相同位置错误,建议先检查宿主机上虚拟磁盘文件的完整性,必要时从快照回滚。

5. 隐藏得更深的几个坑:swapfile、磁盘满、快照膨胀和虚拟化驱动冲突

5.1 swap 分区和 swapfile 挂载失败也会拉你进紧急模式

很多人只关注根分区和业务数据分区,忽略了 swap。系统安装完成后,如果你重新划分了分区,或者用mkswap重置了交换分区,它的 UUID 也会更新,但 fstab 里的旧 UUID 还在,启动时就会尝试挂载一个不存在的交换设备。

在 VM 场景里我遇到过一种更隐蔽的情况:新装系统时用的是 swapfile,后来为了分 swap 分区,改动了 fstab,但 swapfile 文件被删除了,fstab 里却还保留着一行swapfile的条目。为了快速排查,可以直接把这一行注释掉,或者执行swapoff /swapfile后再验证。

5.2 磁盘使用率 100%:启动过程被“没空间”卡住

如果你的根分区使用率达到 100%,系统在启动时无法创建临时文件、无法写日志、甚至无法执行挂载回收,也可能出现紧急模式。这种情况通常伴随一个特征:你能输入 root 密码进提示符,但执行任何命令都显示磁盘已满。

此时需要进入单用户或者紧急模式,第一时间清理磁盘空间。可清理的对象包括:

journalctl --vacuum-time=3d apt clean snap list --all docker system prune -a

清理完成后再检查挂载情况。经验是:生产虚拟机建议给根分区预留 20% 冗余,别把 40G 磁盘整到 39.5G 使用率,这在虚拟化环境里尤其危险,因为虚拟机日志和临时文件并不会因为你磁盘满了就停止写入的意愿。

如果确实需要扩大磁盘,在 VMware 里先编辑虚拟机设置,把磁盘大小加大,然后在 Linux 里用growpart扩展分区、用resize2fs扩展文件系统。扩容后一定记得用blkid重新确认 UUID,不需要改 fstab,因为 UUID 在扩容后一般不会变化。

5.3 快照文件膨胀:VMware/ VirtualBox 的连带故障

VMware 的快照和多层 delta 文件在合理情况下是一种保护机制,但不能无限保留。快照越积越多,虚拟机的读写性能会明显下降,宿主机磁盘空间也会被不断蚕食。快照满了之后,虚拟机内部轻则卡顿,重则 I/O 错误,并可能在重启时进入 emergency 模式。

判断路径是:先在宿主机找到虚拟机目录,查看.vmdk-delta.vmdk.vmsd文件大小。如果-delta文件比基础盘还大,就该考虑合并快照了。在确保虚拟机已关机的前提下,在 VMware 界面选中快照,执行“删除快照”或“转到最新快照”,让它执行合并过程。这个过程需要宿主机的空闲磁盘空间不低于快照文件大小,否则会失败。

5.4 网卡配置和 open-vm-tools 是不是“背锅侠”

排查紧急模式时,你的目光不要 100% 聚焦在 fstab。有些系统进入紧急模式是网络服务失败导致,比如/etc/sysconfig/network-scripts/ifcfg-ens33配置错误、NetworkManager 没有管理对应连接、或者 VMware 虚拟网卡驱动加载失败。

区别在于:网络服务失败通常会被降级到rescue.target而不是emergency.target。但是如果你修改过启动目标,比如/etc/systemd/system/default.target指向了rescue.target,也会出现近似紧急模式的界面。

另外,open-vm-tools缺失不会直接导致紧急模式,但会导致系统在重启时缺少虚拟化渠道通知、控制台分辨率异常,连带着你在排障时看不清输出。建议在一开始安装 Linux 虚拟机时就装上 open-vm-tools:

apt install open-vm-tools -y

6. 退出紧急模式的完整动作和日常加固习惯

6.1 修复完成后的标准退出步骤

在紧急模式提示符下运行修复命令之后,你可能会困惑:现在提示符还在,系统到底算不算修好了?这里给出一套补救标准做法:

  1. 检查mount -a执行结果,确保没有错误输出。
  2. systemctl daemon-reload让 systemd 重新加载修改后的 fstab 配置。
  3. 如果 fstab 被修改过,强烈建议先手打一个同步命令,把修改持久化:
sync
  1. 直接输入reboot重启虚拟机。

如果是 VMware Workstation 环境,重启时留意虚拟机的启动过程到哪个阶段。如果再次落到 emergency 提示符,说明还有没解决的挂载失败,重新回到上面的诊断步骤。如果进入了正常的登录界面,恭喜你,系统已经恢复。

一个更稳妥的做法是:在重启前给虚拟机拍一个快照,或者至少确认当前宿主机的虚拟磁盘有备份。这样即便重启失败,也能原地回滚。

6.2 八个降低紧急模式出现频率的日常习惯

第一,虚拟机内部的关机操作永远走系统内命令,比如shutdown -h nowpoweroff,不要为了让宿主机快点关机而直接“关闭虚拟机电源”。系统内关机流程会完成文件系统卸载和缓存刷写,这一步无法替代。

第二,宿主机磁盘空间保持充足。虚拟机 vmdk 文件、快照文件、内存交换文件都需要磁盘空间,建议宿主机剩余空间不低于虚拟机磁盘文件的 20%。

第三,打快照要有目标性。每次修改 fstab、升级内核、扩展磁盘之前打一个命名清晰的前置快照,比如before-fstab-change,而不是让一堆无差别快照堆积。

第四,定期查看虚拟机的 UUID 和磁盘布局。命令很简单:

lsblk -f blkid

第五,给 fstab 做备份,在每次修改前复制一份:

cp /etc/fstab /etc/fstab.bak.$(date +%F)

第六,安装了新虚拟磁盘后,先在系统里确认分区表,再写 fstab。别一上来就把blkid输出整段复制到 fstab,先人工核对挂载点。

第七,留意 GRUB 的超时和默认内核项。升级内核后旧内核和新内核可能因为磁盘驱动加载顺序不同而产生不同表现,必要时固定内核版本。

第八,使用动态磁盘还是固定大小磁盘并非绝对,但若虚拟磁盘经常用于跑数据库等写入密集型任务,避免在可用空间刚刚够的边界条件下操作。

6.3 如果修复过程中发现虚拟磁盘损坏更加严重

有些情况比较棘手:你进入紧急模式后,发现根分区挂载不了,fsck 也报大量错误,甚至 fsck 过程本身卡死。这时候别再硬抠这台虚拟机,果断走虚拟机层面的救援路线。

在 VMware 中,可以将这台虚拟机的虚拟磁盘文件卸载下来,挂载到另一台正常的 Linux 虚拟机上,以只读方式访问并抢救数据。具体操作是:关闭故障虚拟机,编辑其设置,找到硬盘设备,把“连接到”改为其他虚拟机,或者记录下 vmdk 文件路径,在正常虚拟机里通过“添加已有磁盘”的方式把这块盘加进去。

挂载成功后,在救援虚拟机里执行:

lsblk sudo partx -a /dev/sdb mkdir -p /mnt/rescue mount -o ro /dev/sdb1 /mnt/rescue

把数据拷出来之后,再决定是重建虚拟机还是修复磁盘。经验是:虚拟机的内核和系统配置坏了,重建一个同样的系统再迁移数据,比重装镜像快;虚拟磁盘文件本身坏了,除非数据不可替代,否则没必要花一个通宵去和 fsck 搏斗。

回到开头那句话:紧急模式不是死机,它的本质是 Linux 在保护你。它宁可中断启动,也不愿在你不知情的情况下把只读根分区当成读写分区交给服务使用。搞清楚 systemd 的启动依赖逻辑,把 fstab 和磁盘状态检查做成习惯,你就能在碰到一次紧急模式时把损失控制在半小时以内。我第一次遇到时,在 root 密码都记错的泥潭里打转了快三个小时,后来才发现只是 fstab 里一个 UUID 字母抄错了。这行的教训就是:改动虚拟机的磁盘配置前,先备份,再动手。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询