ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux emergency mode 排查指南:从日志定位到 fstab 与 fsck 修复

Linux emergency mode 排查指南:从日志定位到 fstab 与 fsck 修复 周一早上我照常按下服务器电源键泡了杯咖啡回来屏幕没进系统反而停在了一个黑底白字的界面Welcome to emergency mode!。说实在的第一次遇到这个提示的人多少会慌一下以为系统挂了、数据没了。但只要你理解了 emergency mode 到底是什么、它为什么出现就会发现这其实是 Linux 在启动阶段做了最后的自保动作把控制权交给你让你有机会把问题修好再继续开机。这篇文章我会把 emergency mode 的完整处理链路讲透从它触发的原理到怎么用日志快速定位再到最常见的几种原因逐一排查最后给出日常的预防手段。无论你是刚入行的运维还是自己搭了台 Linux 机器做实验只要照着这个思路走一遍大多数情况下都能把系统救回来。1. emergency mode 不是系统崩溃它是 systemd 的最后一道防线很多教程一上来就让你敲命令但我建议你先搞清楚 emergency mode 的底层逻辑这样后面排查的时候思路会清晰很多。1.1 emergency mode 和 rescue mode 到底有什么区别systemd 时代的 Linux启动过程不是线性的BIOS - 引导 - 内核 - 登录而是一个目标target依赖另一个目标。正常情况下系统会一路走到multi-user.target或者graphical.target。但在这个过程中如果某个关键单元unit失败了systemd 会根据失败的类型做降级degrade处理。降级分两种rescue.target相当于传统 SysVinit 时代的单用户模式会挂载所有本地文件系统然后启动一个最小化的 shell适合做需要文件系统完整可用的修复操作。emergency.target更底层的模式只挂载根文件系统而且通常是只读不启动任何服务不挂载其他分区直接给你一个 root shell。用个生活化的类比rescue mode 像车进了修理厂发动机盖打开了但你还能通电emergency mode 像是车直接拖进了车间只留了一个检修口其他全都断开。两者都是用来救车的但后者更原始。1.2 走到 emergency mode 之前系统经历了什么从按下电源键到看到 emergency mode 提示系统的检查顺序大概是这样的内核启动加载驱动挂载根文件系统那一行systemd[1]的日志就是从这儿开始的。systemd 作为 1 号进程启动开始解析各个 target 的依赖关系。系统尝试挂载/etc/fstab里配置的所有文件系统。如果某个挂载点失败systemd 会先重试重试仍失败就标记该单元为 failed。如果失败的是根文件系统或关键路径比如/usr、/var或者系统检测到文件系统本身有异常它就会放弃继续启动直接进入 emergency mode。也就是说emergency mode 是系统主动踩刹车的结果。它不会让你带着坏掉的文件系统硬启动因为那样可能会让数据损坏雪上加霜。理解了这一点你就知道接下来所有排查的核心就是搞清楚是哪个单元在哪个环节失败了。2. 进入 emergency mode 之后先用日志回答到底发生了什么系统停在 emergency mode 界面后会提示你输入 root 密码登录。如果你连 root 密码都不知道那这篇文章下面的内容都帮不了你——所以日常一定要把 root 密码或者 sudo 权限管理好。登录后你的第一反应应该是执行这条命令而不是去乱修journalctl -xb2.1 journalctl -xb 这个命令到底打印了什么拆开看journalctl是 systemd 的日志查看工具。-x表示补充解释信息比如某条日志对应的单元描述让你不用去翻文档。-b表示只看本次启动boot的日志。如果不加这个参数会从很久之前的历史日志开始输出内容太多反而干扰判断。执行后你会看到大量输出包括内核日志、systemd 启动各单元的过程、失败信息等。这里有个小技巧不要从头到尾细读先把屏幕往下翻到出现Failed或Error字样的地方那往往就是触发 emergency mode 的真凶。实际输出大概是这样的-- Unit data.mount has failed. -- The result is failed. systemd[1]: Mounting /data... systemd[1]: data.mount: Mount process exited, codeexited, status32 systemd[1]: data.mount: Failed with result exit-code.看到Mount process exited, codeexited, status32这种行基本可以确定是挂载出了问题。status32是 mount 命令的退出码代表挂载失败。2.2 日志太多看不过来快速过滤的关键词journalctl -xb输出上千行很正常但你不需要全部看完。我常用的过滤方式journalctl -xb | grep -i fail journalctl -xb | grep -i error journalctl -xb | grep -i not found不过要注意过度依赖 grep 也会有副作用。有些日志虽然包含error字样但可能是无关紧要的警告比如某个非关键服务打印的提示信息而真正的失败信息反而被淹没。建议你先用 grep 定位大概位置然后回到原始日志中看上下文确认失败单元的具体名称和相关依赖。另外systemctl --failed这个命令可以列出所有启动失败的单元一目了然systemctl --failed它会告诉你哪些单元处于failed状态这些单元往往就是需要你处理的对象。2.3 如果根文件系统是只读的怎么办emergency mode 下根文件系统默认以只读方式挂载。你会发现有些命令执行不了或者改了配置后保存失败。这是正常的因为系统要先保证文件系统不被进一步写坏。需要修改配置的时候先把根文件系统重新挂载为读写模式mount -o remount,rw /这个命令执行完你才能对/etc/fstab等配置进行编辑。建议一进来先执行这条命令省得后面每一步都卡壳。3. 最高频的病根/etc/fstab 配置错误根据我这些年的经验触发 emergency mode 的原因里/etc/fstab 写错占了至少一半。这个文件是系统挂载文件系统的说明书一旦内容有问题systemd 不敢跳过只能停下来等你处理。3.1 为什么 fstab 一错系统连正常启动都不敢了fstab 的行格式如下设备来源 挂载点 文件系统类型 挂载选项 dump fsck检查顺序常见写法是 UUID 方式UUID6c8f3d2e-1a2b-4c3d-8e4f-5a6b7c8d9e0f / ext4 errorsremount-ro 0 1 UUID2a1b3c5d-7e8f-4a5b-9c1d-3e2f4a5b6c7d /data ext4 defaults 0 2这里有几个高频出错点UUID 抄错了比如克隆系统盘后分区的 UUID 发生了变化但 fstab 里还写着旧 UUID。系统找不到对应设备自然挂载失败。设备路径写错了有些教程让你写/dev/sdb1但 Linux 的设备名可能重启之后变化比如从/dev/sda变成/dev/sdb导致找不到设备。这就是为什么现代发行版默认推荐使用 UUID 而不是设备路径。挂载选项写错了比如不小心把defaults写成了default或者加了某个文件系统不支持的特性选项。忘了给外接设备加nofail如果你挂载了一块移动硬盘或网络存储但设备没插好或者网络不通系统会一直等待重试最终进入 emergency mode。给这类设备加上nofail选项后挂载失败时系统会跳过不影响主系统启动。在 fstab 中给可插拔设备加 nofail 选项是避免 emergency mode 最有效的单一操作。3.2 定位和修复 fstab 问题的三个实操方法方法一查看日志确认失败单元从journalctl -xb里看到失败单元名称比如data.mount就知道是哪个挂载点出了问题然后打开 fstab 检查对应行cat -n /etc/fstab方法二用blkid确认设备的真实 UUIDblkid这个命令会列出当前系统能识别到的所有块设备及其 UUID、文件系统类型。把 fstab 里写的 UUID 跟blkid输出的结果对比不一致的话直接用正确的 UUID 替换。方法三用mount -a模拟挂载并直接看报错mount -a这个命令会按照 fstab 配置把未挂载的分区全部挂载一遍。如果配置有误它会直接报错告诉你哪个设备找不到哪个文件系统类型错误比在日志里猜要快得多。修改完 fstab 之后也可以再次执行mount -a验证没输出就说明能正常挂载。3.3 修复 fstab 之后怎么验证假设你发现确实是 fstab 里那行/data的 UUID 写错了修复步骤如下用mount -o remount,rw /让根文件系统可写。备份原文件cp /etc/fstab /etc/fstab.bak.$(date %F)。用 vim 编辑/etc/fstab把错误的 UUID 改成正确值如果暂时不确定正确值可以先在这行前面加#注释掉让系统跳过挂载。执行mount -a确认没有报错。执行reboot重启验证。提示如果你只是把出错的行注释掉了重启后系统能正常进入但对应分区不会挂载。等你有空的时候再通过blkid确认正确的 UUID 后补上或者用其他方式处理。4. 文件系统损坏fsck 修复的完整流程如果不是 fstab 的问题那下一个高概率原因就是文件系统本身损坏了。这类问题通常发生在非正常关机、突然断电、强制重启之后。系统启动时检测到文件系统状态异常不敢正常挂载于是把你送进 emergency mode 等你处理。4.1 怎么判断是不是文件系统损坏看日志的时候如果出现类似这样的内容kernel: EXT4-fs (sda1): VFS: Cant find ext4 filesystem fsck.fat 4.1 (2017-01-24) /dev/sda1 contains a file system with errors, check forced.基本可以确定是文件系统层的问题。这种时候不要反复重启尝试因为每次异常启动都可能加重复原。还有一种情况是在正常启动过程中系统提示Checking file systems... /dev/sda1: Inodes that were part of a partially orphaned metafile这其实算是 ext4 文件系统的自检信息不一定代表设备要报废但你需要执行一次完整的文件系统检查。4.2 在 emergency mode 下执行 fsck 的正确姿势在 emergency mode 下根文件系统通常是只读挂载的而执行 fsck 前最好保证目标分区处于未挂载状态否则会有进一步损坏的风险。对于根分区mount -o remount,rw / fsck -f /dev/sda1对于非根分区要确保它没有被挂载umount /dev/sdb1 # 如果已经挂载的话 fsck -f /dev/sdb1参数解释-f强制检查即使文件系统看上去没问题也执行完整扫描。-y对所有交互问题自动回答 yes适合修复时无人值守。不过我个人的习惯是先不加-y跑一遍看看它具体发现了什么问题心里有数后再加-y执行完整修复。如果 fsck 执行过程中发现大量错误可能需要连续运行多次才能完全修复。第一遍修复后重新运行一次确认没有残留错误fsck -f /dev/sda1看到 clean 或者没有错误输出再重启。4.3 xfs 文件系统注意fsck 不是万能的如果你的分区是 xfs 文件系统不能直接用fsck要用xfs_repairxfs_repair -n /dev/sda1 # -n 表示试运行dry run只报告问题不修复 xfs_repair /dev/sda1 # 正式修复xfs 在损坏时修复的成功率没有 ext4 那么高而且对于日志型文件系统有时候直接用xfs_repair反而会丢弃一些数据。所以如果数据非常重要建议在操作前先考虑是否能做好镜像备份比如用dd整盘备份。4.4 修复完怎么验证fsck 结束后输入reboot重启。如果系统能正常进入登录界面说明文件系统修复成功。如果重启后又回到 emergency mode那说明还有更深层的问题比如硬件坏道持续导致文件系统反复损坏这时候要往硬件方向排查了。5. 那些不常见但真实存在的其他触发原因fstab 和文件系统占了大部分场景但偶尔会遇到一些比较隐蔽的原因我把这些年踩过的坑一并列出来供你参考。5.1 硬件相关硬盘坏道、掉盘、线缆松动有时候不是软件配置问题而是硬件本身在报警。比如日志里反复出现ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen sd 0:0:0:0: [sda] Unhandled error code这说明磁盘控制器层已经出问题了可能是硬盘坏道过多、SATA 线缆接触不良或者是 SSD 掉盘。遇到这种情况先做好数据备份再用smartctl检查磁盘健康状态smartctl -a /dev/sda重点看Reallocated_Sector_Ct、Current_Pending_Sector、UDMA_CRC_Error_Count这几项。如果数值异常该换盘就换盘别指望软件层面能完全救回来。5.2 软件配置的隐藏问题SELinux 上下文和关键服务失败在某些启用了 SELinux 的系统上如果文件的安全上下文被打乱了比如错误地执行了mv而不是cp导致上下文丢失系统启动时某些服务可能启动失败极端情况下也会进入 emergency mode。排查方式是先看日志如果出现AVC字样就说明是 SELinux 相关的问题。临时验证手段是在 grub 启动参数里加上selinux0如果系统能正常启动那基本确认是上下文的问题。修复上下文用restorecon -Rv /var/lib/mysql或者touch /.autorelabel reboot5.3 外接设备引起的挂载连锁反应有时候不是系统盘的问题而是你插了一个 U 盘、移动硬盘或者挂载了一块 NFS 网络存储而 fstab 里刚好有对应的记录。由于设备没准备好比如 U 盘没插、网络不通导致挂载失败并触发 emergency mode。这类问题的定位方法跟第 3 章一样但在修复策略上要注意如果该设备本来就是有时候接、有时候不接的建议在 fstab 里加nofail选项并重启验证一劳永逸。UUIDxxx /mnt/usbdrive ext4 defaults,nofail 0 2nofail的作用是告诉 systemd这个挂载点失败没关系不要因此阻塞启动流程。6. 日常预防怎么让自己尽量别再见 emergency modeEmergency mode 本身并不可怕可怕的是你在里面待了很久却发现既没日志、又没备份、还不敢乱操作。如果平时养成了几个好习惯就算真的遇到问题也能在十分钟内解决。6.1 修改 fstab 之前必做三件事第一备份cp /etc/fstab /etc/fstab.bak.$(date %F)第二在执行mount -a验证之前确认你了解这条命令的行为——它会按 fstab 内容把所有未挂载的分区都挂载一遍如果配置有问题当场就能看到报错。第三如果机器远程访问、人不在现场不建议在生产环境随手改 fstab因为万一写错机器重启后就只能去机房或控制台处理了。6.2 重要数据要有独立备份别把文件系统当成保险箱fsck 能修好文件系统的元数据但不代表能把数据百分百救回来。尤其对 xfs 来说一旦损坏严重修复结果可能是文件系统可用了但某些文件变成空文件或丢失了。所以真正需要长期保留的数据请务必走备份方案。我的经验是系统层面做快照数据层面做同步备份双管齐下才不会在 emergency mode 里慌得手足无措。6.3 提前设置好 journald 日志持久化很多发行版默认的 journald 日志不落盘只存在内存里。如果这次启动触发 emergency mode重启之后你可能会发现之前的日志找不到了。建议提前在/etc/systemd/journald.conf里设置Storagepersistent设置后重启 journald 服务systemctl restart systemd-journald这样日志会写到/var/log/journal/以后排查问题就有据可查了。6.4 启动参数里加一个自动功能检查如果你的机器无法现场操作可以在 grub 里临时调整。开机进入 grub 界面按e编辑启动项在linux那一行末尾去掉quiet参数这样启动过程会打印详细日志能直观看到卡在哪一步。对于想要快速恢复的场景还可以在末尾临时加上systemd.unitemergency.target让系统直接进入 emergency mode跳过正常的依赖启动过程适合已知有问题、想快速进 shell 处理的情况。6.5 虚拟化环境的额外保险快照如果你用的是虚拟机操作前先打个快照这是成本最低的保命手段。就算 fstab 写错、文件系统损坏直接回滚快照就能恢复。很多线上事故之所以要花几个小时处理不是因为难修而是因为没有退路只能硬着头皮在损坏状态里抠数据。有快照的话见势不对先回滚把系统恢复正常再慢慢研究原始问题也不迟。根据我自己的经验真正常遇到 emergency mode 的场景反而是在那种改了个配置、顺手 reboot 一下的瞬间——比如加了一块新盘、调整了挂载参数、或者克隆了虚拟机没改 UUID。只要你能冷静地看完日志、定位到失败单元、一步步验证修复十次里有九次是能救回来的。哪怕真遇到硬件损坏有了日志和备份你也能心里有底地决定是修盘还是换盘。希望这篇文章能帮你少踩一些坑至少在下次见到 emergency mode 时心里有个清晰的排查路径。
返回列表