一行 fstab 写错整台服务器开不了机:一次 Linux 开机挂载排查复盘

给服务器加数据盘往 /etc/fstab 写了一行,几周后一次例行重启机器再没起来,控制台停在 emergency mode 急救模式。排查梳理:fstab 不是可挂可不挂的清单,开机时 systemd 把每一行都变成必须完成的挂载任务,任意一行失败都会拖垮 local-fs.target 让系统进急救模式;第 1 列用 /dev/vdX 设备名很危险设备名会漂要用 UUID,systemd 找不到设备不会跳过而是死等 90 秒超时;数据盘和网络盘选项必须加 nofail 挂不上不挡开机,配 x-systemd.device-timeout 限制等待,第 6 列 fsck 顺序非根盘填 0;掉进急救模式先 mount -o remount,rw / 把根挂成可写再改 fstab,改完重启前必须 mount -a 和 findmnt --verify 验证不报错才能重启,以及一套 fstab 与开机挂载排查纪律。

2024 年,我给一台服务器加了一块数据盘,挂在 /data 上。为了让它每次开机自动挂载,我顺手往 /etc/fstab 里加了一行。加完我 mount /data 试了一下,挂上了,没问题,我就把这事翻篇了。几周后的一个深夜,这台机器因为别的原因重启了一次——然后它就再也没回来。服务全挂,SSH 连不上。我急忙开控制台 VNC,屏幕停在一个我很陌生的地方:Welcome to emergency mode!,下面让我输入 root 密码进维护模式。我当时第一反应是:不就是一块数据盘没挂上吗?有什么大不了的,大不了那块盘不用了,系统该正常起来啊——一行配置写错,顶多是那一行不生效,凭什么把整台机器都拖进了"急救模式"?我一直觉得 /etc/fstab 不过是一张"开机要挂哪些盘"的清单,清单里某一项有问题,跳过它就是了。可现在,就因为那一行,整台服务器开!不!了!机!了。我盯着那个 emergency mode 想了很久,最后才明白,我把 /etc/fstab 这张"清单",理解得太轻了。这件事逼着我把 Linux 的 fstab、开机挂载、急救模式这一整套彻底理清了。本文复盘这次实战。

问题背景

环境:CentOS 7,一台服务器,加了一块数据盘,写进了 /etc/fstab
事故现象:
- 几周前给 /etc/fstab 加了一行,自动挂载数据盘
- 一次例行重启后,机器再没起来,SSH 连不上
- ★ 控制台停在 emergency mode(急救模式),要 root 密码

现场排查(在控制台 VNC 里):
# 1. 屏幕上的画面
Welcome to emergency mode!
... Cannot open access to console, the root account is locked.
Give root password for maintenance
(or press Control-D to continue):

# 2. ★ 输入 root 密码进去后,看开机日志
$ journalctl -xb | grep -i -E 'fail|timeout|mount'
... Timed out waiting for device /dev/vdb1.
... Dependency failed for /data.
... Dependency failed for Local File Systems.       # ★ 关键
# ★ 一个挂载失败,把"本地文件系统"这个开机阶段整个拖垮了。

# 3. ★ 看那行闯祸的 fstab
$ cat /etc/fstab
...
/dev/vdb1   /data   xfs   defaults   0 0
#  ★ 问题:这块盘这次没认到 /dev/vdb1,设备名漂了

根因(后来想清楚的):
1. ★ /etc/fstab 不是一张"可挂可不挂的清单"。开机时,
   systemd 会把里面【每一行】都变成一个开机要完成的
   【挂载任务】,而且默认是【必须成功】的任务。
2. 开机过程里有一个阶段叫"Local File Systems"
   (local-fs.target),它要等 fstab 里【所有】该挂的
   都挂好,才算完成,后面的阶段才能继续。
3. ★ 我那行写的是 /dev/vdb1。但设备名(vdb/vdc...)
   是【开机时按发现顺序临时分配】的,不固定 —— 这次
   重启,那块盘没认到 vdb1,挂载就找不到设备。
4. systemd 找不到设备,不会"跳过",而是【死等】这个
   设备出现,等到超时(默认 1 分 30 秒)。
5. ★ 超时后,这个挂载任务【失败】,连带 local-fs.target
   失败 —— 开机流程走不下去,systemd 只好把系统切到
   【emergency mode】,等人来救。
6. 一行 fstab 写错 = 整台机器开不了机。它从来不是
   "不生效"那么轻 —— 它会【挡住整个开机流程】。
fstab 里任何一行挂载失败,默认都会让开机卡死。

修复 1:/etc/fstab 写错为什么会"开不了机"

# === ★ 先纠正最核心的误解:fstab 不是"清单",是"开机任务" ===

# === 我以为的 fstab vs 真实的 fstab ===
# 我以为:fstab 是一张"开机时尝试挂载这些盘"的清单,
#   挂不上的,跳过就好,不影响系统起来。
# ★ 真相:开机时,systemd 把 fstab 里【每一行】都
#   翻译成一个【挂载单元(mount unit)】,并且默认
#   把它当成【开机必须完成】的一步。

# === ★ 开机流程里那个会被拖垮的阶段 ===
# Linux 开机是一连串"阶段(target)"按顺序推进的。
#   其中有一个阶段叫 local-fs.target(本地文件系统)。
# ★ 这个阶段的任务,就是把 fstab 里所有本地盘都挂好。
#   它【必须全部成功】,开机才能进入下一阶段。
# 只要 fstab 里有一行挂不上,local-fs.target 就失败,
#   ★ 整个开机流程在这里【断掉】。

# === systemd 找不到设备时,不是跳过,是"死等" ===
# 我那行写的设备这次不存在。systemd 的反应不是
#   "哦没有就算了" —— 而是【等】:它认为这个设备
#   也许马上就会出现(比如 U 盘、网络盘慢),
#   于是死等,直到【超时】(默认 90 秒)。
# ★ 超时 -> 挂载失败 -> local-fs.target 失败 ->
#   开机走不下去 -> 切进 emergency mode。

# === 在急救模式里,确认就是 fstab 的锅 ===
$ journalctl -xb | grep -i -E 'dependency failed|timed out|mount'
Timed out waiting for device ...
Dependency failed for /data.
Dependency failed for Local File Systems.        # ★ 实锤
# ★ "Dependency failed for Local File Systems" ——
#   看到这句,基本就是 fstab 里某一行挂载出了问题。

# === 看到底哪个挂载单元失败了 ===
$ systemctl --failed
$ systemctl list-units --type=mount | grep -i fail
# ★ 失败的那个 mount unit,名字就对应着 fstab 里的挂载点。

# === ★ 一句话认知 ===
# fstab 里的每一行,都是开机的一个"必答题"。
#   答错一题(挂载失败),默认就【整张卷子作废】——
#   系统不开了。它远不是"不生效"那么轻。

修复 2:看懂 fstab 每一列——错在哪一列都要命

# === ★ 把 fstab 的 6 列彻底讲清楚,每列错了什么后果 ===

# === fstab 一行的 6 个字段 ===
$ cat /etc/fstab
# <设备>          <挂载点>  <类型>  <选项>      <dump> <fsck顺序>
UUID=abcd-1234   /data    xfs    defaults    0      0
# 第1列 设备     :挂哪个盘 —— 设备名 或 UUID 或 LABEL
# 第2列 挂载点   :挂到哪个目录
# 第3列 类型     :文件系统类型 xfs/ext4/...
# 第4列 选项     :挂载选项,defaults / nofail / ro ...
# 第5列 dump     :是否被 dump 备份,几乎都填 0
# 第6列 fsck顺序 :★ 开机时 fsck 检查它的顺序,0=不检查

# === ★ 第 1 列:别用 /dev/vdb1 这种设备名 ===
# 设备名(vda/vdb/vdc)是开机时【按发现顺序临时分配】的,
#   ★ 加盘、换盘、甚至单纯重启,都可能让它"漂"。
# 我这次就是栽在这:写的 /dev/vdb1,重启后那块盘
#   没认到 vdb1 -> 挂载找不到设备 -> 开机失败。
# ★ 正解:用 UUID —— 它是文件系统的"身份证",
#   只要不重新格式化,永远不变。
$ blkid /dev/vdb1
/dev/vdb1: UUID="abcd-1234-..." TYPE="xfs"
# ★ 把 blkid 查到的 UUID 写进 fstab 第 1 列。

# === 第 2 列:挂载点目录必须真实存在 ===
# fstab 不会帮你建目录。挂载点不存在,挂载会出问题。
$ mkdir -p /data

# === 第 3 列:类型写错也会挂载失败 ===
# xfs 的盘写成 ext4,挂载直接报错。拿不准用 blkid 看。

# === ★ 第 4 列:选项里 nofail 是"保命选项"(见修复 4)===
# defaults = 默认一套选项。加上 nofail,这行挂载失败
#   就【不会挡开机】—— 这是数据盘最该加的。

# === ★ 第 6 列:fsck 顺序,非根盘建议填 0 ===
# 第 6 列非 0,开机时会对这个盘跑 fsck 检查。
#  - 根分区 /  填 1
#  - 其他盘   填 2 或 ★ 0(0 = 开机不检查)
# ★ 如果设备不存在 / 文件系统损坏,而第 6 列非 0,
#   开机 fsck 这一步就会失败,同样把你拖进急救模式。
# 数据盘把第 6 列填 0,能少一个开机失败的雷。

修复 3:掉进急救模式,怎么改回来

# === ★ 系统进了 emergency mode,救援步骤 ===

# === 第一步:进维护 shell ===
# emergency mode 屏幕上提示 "Give root password"。
#   输入 root 密码,回车,就进了一个维护用的 shell。
# ★ 注意:此时根文件系统常常是【只读】挂载的,
#   你直接改 /etc/fstab 会发现存不了。

# === ★ 第二步:把根文件系统重新挂成可写 ===
$ mount -o remount,rw /
# ★ remount,rw:把已挂载的 / 重新挂载为可读写。
#   这一步做完,才能编辑 /etc/fstab。

# === 第三步:改回那行闯祸的 fstab ===
$ vi /etc/fstab
# 两种改法,二选一:
#  A. 先把那行【注释掉】(行首加 #),让系统先能开起来:
#     # /dev/vdb1   /data   xfs   defaults   0 0
#  B. 直接改对:把设备名换成 UUID,选项加 nofail:
#     UUID=abcd-1234  /data  xfs  defaults,nofail  0 0
# ★ 救火阶段,推荐先用 A 注释掉,让机器先起来,
#   起来之后再从容地把这块盘正确挂上。

# === ★ 第四步(关键):重启前,先验证 fstab 对不对 ===
$ mount -a
# ★ mount -a = 按 fstab 把所有该挂的都挂一遍。
#   它【不报错】,才说明 fstab 没问题,可以放心重启。
#   ★ 如果它报错,就【别重启】—— 否则又掉回急救模式。
$ findmnt --verify          # 更专业的 fstab 校验工具
# ★ findmnt --verify 会逐行检查 fstab 的合法性。

# === 第五步:确认无误,重启 ===
$ systemctl reboot
# 或者在急救模式按 Ctrl-D 尝试继续开机。

# === ★ 如果连 root 密码都进不去 / 忘了 ===
# 那就只能上更底层的手段:开机在 grub 菜单按 e,
#   在 linux 那行末尾加 rd.break 或 init=/bin/bash,
#   进一个最小环境,再 remount,rw 改 fstab。
# ★ 云服务器更简单:很多云厂商控制台支持"进入救援模式"
#   或挂载到另一台机器上改文件 —— 善用云控制台。

修复 4:nofail——让挂载失败不再挡开机

# === ★ 真正的预防核心:给数据盘加 nofail ===

# === 问题的本质 ===
# fstab 默认每一行都是"开机必须成功"。对【根分区】
#   这合理 —— 根挂不上,系统根本没法跑。
# ★ 但对一块【数据盘】,这就太刚性了:它没挂上,
#   系统其实完全可以先正常起来,数据盘的事回头再说。
# 默认行为却是:数据盘挂不上,也把整机拖垮。

# === ★ nofail:把"必须成功"改成"挂不上就算了" ===
$ vi /etc/fstab
UUID=abcd-1234  /data  xfs  defaults,nofail  0 0
#                                  ^^^^^^ ★ 关键
# 加了 nofail:开机时这块盘挂上最好,
#   ★ 挂不上,systemd 不报错、不拖垮开机,直接跳过。
# 系统照常起来,只是 /data 暂时空着 —— 这才是数据盘
#   应有的"软失败"行为。

# === ★ 配合 x-systemd.device-timeout,别死等 90 秒 ===
UUID=abcd-1234  /data  xfs  defaults,nofail,x-systemd.device-timeout=10  0 0
# x-systemd.device-timeout=10:等这个设备最多等 10 秒,
#   还没出现就放弃(配合 nofail 就是直接跳过)。
# ★ 不加这个,即便有 nofail,开机也可能干等满 90 秒
#   才往下走 —— 加上它,开机不会被拖那么久。

# === 网络存储(NFS 等)更要这套选项 ===
# 网络盘开机时网络可能还没好,极易挂载超时。
$ cat /etc/fstab
1.2.3.4:/share  /mnt/nfs  nfs  defaults,nofail,_netdev,x-systemd.device-timeout=10  0 0
# - _netdev:告诉系统"这是网络设备",等网络就绪再挂
# - nofail :挂不上也不挡开机

# === ★ 一条准则 ===
# 除了【根分区和必要的系统分区】,
#   ★ 其他所有写进 fstab 的盘,都该加 nofail。
# 这一个选项,就能避免"一块数据盘拖垮整台机器"。

修复 5:改 fstab 的安全流程

# === ★ 这次事故最该记住的:改 fstab 的安全流程 ===

# === ★ 铁律:改完 fstab,重启前必须 mount -a 验证 ===
# 我这次的根本错误,是改完 fstab 就【没再管它】,
#   几周后一次重启才暴雷 —— 改和暴雷隔了几周,
#   等出事时,我都快忘了动过 fstab。
# ★ 改 fstab 后,必须【当场】验证它能不能正确挂载。

# === 安全改 fstab 的完整步骤 ===
# 第 1 步:改之前,先备份
$ cp /etc/fstab /etc/fstab.bak

# 第 2 步:用 UUID,先查出来
$ blkid /dev/vdb1
/dev/vdb1: UUID="abcd-1234" TYPE="xfs"

# 第 3 步:编辑 fstab,用 UUID + nofail
$ vi /etc/fstab
UUID=abcd-1234  /data  xfs  defaults,nofail,x-systemd.device-timeout=10  0 0

# 第 4 步:★★ 当场验证 —— 这一步绝不能省 ===
$ mount -a
# ★ mount -a 不报错 = fstab 这几行能正确挂载。
$ findmnt --verify
# ★ findmnt --verify 逐行校验 fstab 语法/逻辑。
$ df -h /data        # 确认 /data 真的挂上了
$ mount | grep /data # 再确认一遍

# 第 5 步:让 systemd 重新认识 fstab(它有缓存)
$ systemctl daemon-reload
# ★ systemd 会把 fstab 解析成 mount unit 缓存起来,
#   改完 fstab 做一次 daemon-reload,让它重读。

# === ★ 验证开机挂载行为,而不是只验证"现在能挂" ===
# mount -a 只证明"现在手动挂能挂上"。要更稳妥,
#   可以重启前再过一遍脑子:设备名换 UUID 了吗?
#   数据盘加 nofail 了吗?第 6 列是 0 吗?
# ★ 三个都 yes,这次重启基本就稳了。

# === 出了问题,还能用备份秒回 ===
$ cp /etc/fstab.bak /etc/fstab     # 第 1 步的备份,这时救命

修复 6:fstab 与开机挂载排查纪律

# === 这次事故暴露的认知盲区,定几条纪律 ===

# === 1. ★ fstab 每一行都是开机必答题,答错就开不了机 ===
# 它不是"清单",挂载失败默认会把整个开机流程拖垮。

# === 2. ★ fstab 第 1 列用 UUID,不要用 /dev/vdX ===
$ blkid          # 设备名会漂,UUID 才稳定

# === 3. ★ 数据盘 / 网络盘,选项必加 nofail ===
# 再配 x-systemd.device-timeout,别让开机死等。

# === 4. 非根盘第 6 列(fsck 顺序)填 0 ===
# 设备不在 / 文件系统坏,fsck 非 0 也会拖垮开机。

# === 5. ★★ 改完 fstab,重启前必须 mount -a 验证 ===
$ mount -a ; findmnt --verify
# 不报错才能重启。报错就别重启,先改对。

# === 6. 改 fstab 前先 cp 一份备份 ===
$ cp /etc/fstab /etc/fstab.bak

# === 7. 掉进急救模式:remount,rw 后改 fstab ===
$ mount -o remount,rw /     # 然后 vi /etc/fstab 注释掉坏行

# === 8. 排查"开机进急救模式"的步骤链 ===
$ 输 root 密码进维护 shell
$ journalctl -xb | grep -i 'dependency failed'   # ① 确认是不是 fstab
$ mount -o remount,rw /                           # ② 根挂成可写
$ vi /etc/fstab                                   # ③ 注释/改对坏行
$ mount -a                                        # ④ ★ 验证不报错
$ systemctl reboot                                # ⑤ 重启
# 按这个顺序,fstab 引起的开机失败基本能救回来。

命令速查

需求                        命令
=============================================================
查盘的 UUID 和文件系统类型   blkid /dev/vdb1
按 fstab 挂载所有盘(验证)  mount -a
逐行校验 fstab 合法性        findmnt --verify
把根文件系统重挂为可写       mount -o remount,rw /
看开机失败日志              journalctl -xb | grep -i 'dependency failed'
看失败的单元                systemctl --failed
看挂载类单元                systemctl list-units --type=mount
改完 fstab 让 systemd 重读   systemctl daemon-reload
备份 fstab                  cp /etc/fstab /etc/fstab.bak
确认某目录挂载情况          df -h /data ; mount | grep /data

口诀:fstab 每行都是开机必答题,挂载失败默认拖垮整个开机
      第1列用 UUID 别用设备名,数据盘加 nofail,改完重启前必须 mount -a

避坑清单

  1. fstab 不是可挂可不挂的清单,开机时每一行都是必须完成的挂载任务
  2. fstab 任意一行挂载失败,会拖垮 local-fs.target,导致系统进急救模式开不了机
  3. 第 1 列用 /dev/vdX 设备名很危险,设备名按发现顺序临时分配会漂,要用 UUID
  4. systemd 找不到设备不会跳过而是死等,默认等 90 秒超时后才判定挂载失败
  5. 数据盘和网络盘的挂载选项必须加 nofail,挂不上时不挡开机系统照常起来
  6. 配合 x-systemd.device-timeout 限制等待时间,否则即便有 nofail 开机也可能死等
  7. fstab 第 6 列是 fsck 检查顺序,非根盘填 0,设备不在而非 0 也会拖垮开机
  8. 改完 fstab 重启前必须 mount -a 验证,不报错才能重启,报错就别重启
  9. findmnt --verify 能逐行校验 fstab 的合法性,改完一起用上更稳妥
  10. 掉进急救模式先 mount -o remount,rw / 把根挂成可写,才能编辑修复 fstab

总结

这次"一行 fstab 写错、整台服务器开不了机"的事故,纠正了我一个关于 /etc/fstab 的、轻描淡写的误解。在我的脑子里,/etc/fstab 一直是一张"清单"——一张写着"开机的时候,顺便把这几块盘也挂上"的、温和的、建议性质的清单。既然是"顺便",那它的语气在我听来就是温和的:能挂上,挂上;万一挂不上,那这一项就跳过呗,系统该怎么起来还怎么起来。正是这个"清单"的心智模型,让我在加完那行配置、mount 测试通过之后,心安理得地把这件事彻底翻篇了——在我看来,我最坏的下场,也不过是某天那块数据盘没挂上而已,一件小事。所以几周后,当那台服务器重启后再没回来、控制台冷冰冰地停在 emergency mode 时,我的第一反应不是排查,而是难以置信:一行关于"数据盘"的配置,凭什么能让一台机器整个开不了机?这个"凭什么",暴露的正是我那个"清单"模型的彻底失效。复盘到根上,我才真正看清 /etc/fstab 在开机这件事里的真实分量。它根本不是一张温和的、建议性的清单。在 systemd 的眼里,这个文件里的每一行,都是一道开机过程中【必须答对】的题。开机不是一蹴而就的,它是一连串阶段按顺序推进的接力,其中有一棒,叫"本地文件系统"——这一棒的任务,就是把 fstab 里写明的盘,一块不少地全挂好。它要的是"全部成功",而不是"尽量成功"。只要有一行挂不上,这一棒就算掉了棒,后面所有的阶段都跑不下去,整场接力就此中断。而我那行配置错得又格外隐蔽:我用了 /dev/vdb1 这个设备名,却不知道设备名是开机时按发现顺序临时派发的、会"漂"的东西。那次重启,那块盘没再被认成 vdb1,于是 systemd 拿着一个找不到的设备名,既不跳过、也不报错,只是固执地、沉默地等下去,等满了九十秒的超时,才终于判定这道题"答错了"——然后,把整台机器交给了急救模式。一行配置,没有"不生效"这种轻飘飘的中间地带,它要么答对,要么让整台机器停摆。这次最大的收获,是我意识到,我对一个配置文件"分量"的判断,常常是错的,而且错得很危险。我习惯于按一个文件"看起来"的样子去掂量它的轻重:fstab 看起来朴素、简单、就几行,我就以为它无足轻重。可一个配置文件真正的分量,从来不取决于它有几行、长什么样,而取决于【谁在什么时候、以什么样的刚性去消费它】。fstab 被消费的时机,是系统最脆弱的开机阶段;消费它的方式,是不容失败的强依赖。一个朴素的文件,放在这样一个位置上,它的每一行都重若千钧。所以下一次,当我要动一个看起来"无关紧要"的配置文件时,我会先问自己一个问题:这个文件,是在系统的哪个环节、被谁、以多硬的方式读取和执行的?想清楚了这个,我才知道我手里这一行字,到底是一根羽毛,还是一颗随时会引爆的雷。然后,在按下重启之前,老老实实地、当场地,把它验证一遍。

—— 别看了 · 2026
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理 邮箱1846861578@qq.com。
Linux教程

load 高达 28 CPU 却闲着:一次 Linux 负载与 iowait 排查复盘

2026-5-20 20:51:54

Linux教程

cron 配置都对脚本却不执行:一次 Linux 定时任务环境排查复盘

2026-5-20 20:59:10

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索