挂个数据盘把服务器搞到开不了机:一次 /etc/fstab 排查复盘

给服务器挂块数据盘,往 /etc/fstab 加了一行,一周后重启卡在 emergency mode 起不来。排查梳理:裸盘到能用要走的几道工序、mount 临时挂载与 fstab 永久挂载的本质区别、fstab 六个字段、为什么必须用 UUID 不用 /dev/sdX、数据盘漏写 nofail 让一块盘有权否决整机开机、emergency mode 自救流程,以及一套挂载排查纪律。

2024 年,我给一台服务器加了一块新的数据盘,要挂到 /data 给数据库用。挂载本身很顺利:分区、格式化、mount,几条命令下去,df 里清清楚楚多出了 /data,我往里写文件也一切正常。为了让这块盘开机后能自动挂上,我又往 /etc/fstab 里加了一行——这一步我做得飞快,凭着记忆敲了一行,看着"挺像那么回事",保存退出。当晚没出任何问题。可一周后,这台机器因为别的原因重启了一次,然后……它就再也没起来。SSH 连不上,我让机房同事接了显示器过去,屏幕上是一行刺眼的字:Welcome to emergency mode。一块只是用来存数据的盘,我只是想让它"开机自动挂载",怎么就把整台服务器搞到开不了机了?这件事逼着我把 Linux 的磁盘挂载、/etc/fstab、文件系统这一整套彻底理清了。本文复盘这次实战。

问题背景

环境:CentOS 7,给服务器加了一块新数据盘
事故现象:
- 手动 mount 新盘到 /data,完全正常,能读能写
- 往 /etc/fstab 加了一行让它开机自动挂载
- 一周后机器重启,卡在 emergency mode,系统起不来

现场排查(机房接显示器):
# 1. emergency mode 下,先看是谁拦住了开机
Welcome to emergency mode!
... see "systemctl status" ...
Give root password for maintenance:

# 2. 输入 root 密码进去,看启动日志
$ journalctl -xb | grep -i 'fail\|mount'
... Failed to mount /data.
... Dependency failed for Local File Systems.
... systemd[1]: Mounting /data...  ->  failed
# ★ 真相:开机挂载 /data 失败,把整个启动流程拖垮了

# 3. 看我当初加的那行 fstab
$ cat /etc/fstab
...
/dev/sdb1   /data   ext4   defaults   0 0
#  ★ 问题就在这一行

# 4. 看现在这块盘的设备名
$ lsblk
sdb            8:16   0   100G  0 disk
└─sdb1         8:17   0   100G  0 part            # 没挂载

根因(后来想清楚的):
1. ★ fstab 里我写的是 /dev/sdb1。但磁盘的设备名
   (sdb/sdc...)是【内核按发现顺序临时分配】的,
   它【不保证每次开机都一样】。
2. 那次重启,可能因为加了别的设备 / 识别顺序变化,
   这块盘的名字不再是 sdb1 -> fstab 那行指向了
   一个不存在的设备 -> 挂载失败。
3. ★ 致命的是:fstab 里的条目,默认是开机的【强依赖】。
   一个挂载失败,systemd 认为"本地文件系统没准备好",
   直接中止正常启动,掉进 emergency mode。
4. 两个错叠加:① 用了会变的设备名,不该用;
   ② 没加 nofail,让一块数据盘的挂载,有权否决整个开机。
fstab 写错,代价是整台机器开不了机。

修复 1:一块新磁盘到系统能用,要走几步

# === ★ 先理清:一块裸盘到能往里写文件,中间有几道工序 ===
# 裸盘 -> [分区] -> [格式化建文件系统] -> [挂载到目录] -> 能用

# === 第一步:看看系统认到了哪些盘 ===
$ lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda      8:0    0   50G  0 disk
└─sda1   8:1    0   50G  0 part /            # 系统盘,已挂在 /
sdb      8:16   0  100G  0 disk              # ★ 新盘,还是裸的
# lsblk 一眼看清:有哪些盘、分了哪些区、各自挂在哪。

# === 第二步:给新盘分区(也可以整盘不分区直接用)===
$ fdisk /dev/sdb                # 交互式分区,大于 2T 用 parted
# 或用 parted:parted /dev/sdb mklabel gpt + mkpart ...
$ lsblk                         # 分完应能看到 sdb1

# === 第三步:格式化 —— 在分区上【建立文件系统】===
$ mkfs.ext4 /dev/sdb1           # 建 ext4 文件系统
# 或 mkfs.xfs /dev/sdb1         # CentOS 7 默认更推荐 xfs
# ★ 格式化会清空分区数据,执行前务必确认设备名没敲错!

# === 第四步:挂载 —— 把文件系统【接到目录树的某个点】===
$ mkdir /data                   # 先准备好挂载点目录
$ mount /dev/sdb1 /data         # 把文件系统挂到 /data
$ df -h /data                   # 确认挂上了
/dev/sdb1   100G  ...  /data

# === ★ "挂载"到底是什么意思 ===
# Linux 没有 C盘 D盘。所有东西都在【一棵目录树】上。
# 挂载,就是把一个文件系统,"接"到这棵树的某个目录上 ——
# 从此访问那个目录,就是在访问那块盘。
# 挂载点目录原有的内容,会在挂载期间被【临时遮盖】。

修复 2:mount 临时挂载 vs /etc/fstab 永久挂载

# === ★ 这次踩坑的认知起点:mount 命令的效果【不持久】 ===

# === mount 命令:只是【当下这次】把盘挂上 ===
$ mount /dev/sdb1 /data
# 它确实把盘挂好了,能读能写 —— 但这只是【运行时】状态。
# ★ 机器一重启,这次手动 mount 的效果【全部消失】,
#   /data 又变回一个空目录。

# === 想让挂载"开机自动恢复",只有一个正路:写 /etc/fstab ===
$ cat /etc/fstab
# <设备>          <挂载点>  <类型> <选项>       
UUID=xxxx-xxxx   /         xfs    defaults    0 0
UUID=yyyy-yyyy   /data     ext4   defaults,nofail 0 2
# 开机时,systemd 会读这个文件,把里面每一行都挂上。

# === ★ 卸载 ===
$ umount /data                  # 卸载
$ umount /dev/sdb1              # 用设备名卸也行
# 卸载失败提示 "target is busy" -> 有进程正在用这个目录:
$ lsof /data                    # 或 fuser -m /data,看谁占着
$ cd ~                          # 最常见:你自己 shell 就 cd 在里面

# === ★ 这次的根本误区 ===
# 我以为 mount 命令"挂好了"就一劳永逸 ——
# 其实 mount 管"现在",fstab 管"以后每次开机"。
# 真正危险的不是 mount,是我往 fstab 里【写错了一行】。

# === 看当前系统所有挂载情况 ===
$ mount | column -t            # 列出所有已挂载的文件系统
$ findmnt                      # ★ 树状展示,更直观
$ findmnt /data                # 单独看某个挂载点的详情

修复 3:/etc/fstab 六个字段——逐个看懂

# === ★ fstab 每一行,是空格/制表符分隔的【六个字段】 ===
# UUID=yyyy-yyyy   /data   ext4   defaults,nofail   0   2
#      ①            ②       ③         ④            ⑤   ⑥

# === 字段①:设备 —— 挂【哪一块】 ===
# 可以写 /dev/sdb1,也可以写 UUID=... 或 LABEL=...
# ★ 强烈建议用 UUID(下一节专门讲为什么)。

# === 字段②:挂载点 —— 挂到目录树的【哪个目录】 ===
# 这个目录必须【已经存在】。

# === 字段③:文件系统类型 ===
# ext4 / xfs / vfat / ntfs / swap ... 不确定可写 auto 让系统自己认。

# === 字段④:挂载选项 —— ★ 坑最多、也最重要的一栏 ===
# defaults  一组常用默认选项(rw,suid,dev,exec,auto,nouser,async)
# ro / rw   只读 / 读写
# noatime   不记录文件访问时间 —— 减少写、提性能,数据盘常加
# ★ nofail  挂载失败【也不让它阻塞开机】—— 这次的救命选项!
# ★ _netdev 网络设备(NFS等),等网络就绪后再挂
# 多个选项用【逗号】连,中间不要有空格。

# === 字段⑤:dump —— 是否被 dump 工具备份 ===
# 几乎都填 0。基本是历史遗留,不用纠结。

# === 字段⑥:fsck 开机检查顺序 —— ★ 别乱填 ===
# 0 = 开机不检查这个文件系统
# 1 = ★ 只给【根文件系统 /】用
# 2 = 其他需要检查的文件系统
# 数据盘填 2,根分区填 1,swap 和不想检查的填 0。

# === ★ 一行安全的数据盘 fstab,长这样 ===
UUID=yyyy-yyyy  /data  ext4  defaults,nofail,noatime  0  2
# 用 UUID、带 nofail —— 这两点,正是我当初那行缺的。

修复 4:为什么用 UUID 不用 /dev/sdb1

# === ★ 这次事故的直接导火索:fstab 里写了 /dev/sdb1 ===

# === 设备名 sda/sdb/sdc 是【不稳定】的 ===
# 这些名字,是内核在开机时,【按发现磁盘的顺序】临时分配的。
# ★ 它不是磁盘的"固有属性",只是这次开机的一个临时编号。
# 什么时候会变:
#   - 加了 / 拔了别的磁盘
#   - 换了磁盘插槽 / 控制器
#   - 内核、驱动识别顺序变化
# -> 你这次的 sdb1,下次开机可能就成了 sdc1。
# fstab 里写死 /dev/sdb1,等于把挂载赌在一个会变的名字上。

# === ★ 正解:用 UUID —— 文件系统的"身份证",终身不变 ===
# UUID 是格式化时写进文件系统的全局唯一标识,
# 盘插哪个口、设备名怎么变,UUID 都【不变】。

# === 查一块盘的 UUID ===
$ blkid /dev/sdb1
/dev/sdb1: UUID="a1b2c3d4-..." TYPE="ext4"
# 或看全部:
$ lsblk -f
NAME   FSTYPE  UUID                    MOUNTPOINT
sdb1   ext4    a1b2c3d4-...

# === fstab 里就用 UUID 写 ===
UUID=a1b2c3d4-...   /data   ext4   defaults,nofail   0 2

# === 也可以用 LABEL(卷标),同样稳定 ===
$ e2label /dev/sdb1 datadisk      # 给 ext 文件系统打卷标
$ xfs_admin -L datadisk /dev/sdb1 # xfs 打卷标
# fstab 里:LABEL=datadisk  /data  ...

# === ★ 一句话纪律 ===
# fstab 里【永远】用 UUID 或 LABEL,【永远不要】用 /dev/sdX。
# 设备名是给"此刻"看的,fstab 是给"以后每次开机"用的 ——
# 用一个临时的名字,去定义一件长期的事,迟早出事。

修复 5:fstab 写错导致开机失败——怎么自救

# === ★ fstab 写错,最严重的后果就是这次:开不了机 ===
# 一个 fstab 条目挂载失败,默认会让 systemd 判定
# "本地文件系统未就绪",中止启动,进入 emergency mode。

# === emergency / rescue mode 里怎么自救 ===
# 1. 屏幕提示 "Give root password for maintenance",输 root 密码
# 2. ★ 此时根分区往往是【只读】的,先把它改成可读写:
$ mount -o remount,rw /
# 3. 改回那行有问题的 fstab(用 vi 把错误行修对或注释掉):
$ vi /etc/fstab
# 4. ★ 改完【先验证】,别急着重启:
$ mount -a
# mount -a = 按 fstab 把所有条目挂一遍。
#   没报错 -> fstab 现在是对的,可以放心重启;
#   报错   -> 哪行错继续改,直到 mount -a 干净通过。
# 5. 确认无误再 reboot。

# === ★ 真正的护身符:数据盘那行一定加 nofail ===
UUID=...  /data  ext4  defaults,nofail  0 2
# 加了 nofail:这个盘开机时挂不上,systemd 只是【跳过它】,
#   继续正常启动 —— 系统照样进得去,你登进去再慢慢修。
# ★ 一块数据盘的挂载,绝不该有权"否决"整台机器的开机。

# === 还可以再加 x-systemd 选项,更稳 ===
UUID=...  /data  ext4  nofail,x-systemd.device-timeout=10  0 2
# x-systemd.device-timeout=10 :等这个设备最多 10 秒,
#   超时就放弃,不会傻等导致开机巨慢。

# === ★ 改 fstab 的安全流程(以后每次都这么做)===
# 1. 改之前先备份:cp /etc/fstab /etc/fstab.bak
# 2. 数据盘行务必用 UUID + 带 nofail
# 3. 改完【不要直接重启】,先 mount -a 验证
# 4. mount -a 无报错,再重启 —— 这一步能挡掉 99% 的开机事故

# === 万一连 emergency mode 都进不去 ===
# 用安装盘 / LiveCD 引导进救援环境,chroot 到系统盘,
# 改 /etc/fstab 后重启。云服务器则用控制台的"救援模式"。

修复 6:磁盘挂载排查纪律

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

# === 1. ★ mount 命令不持久,重启就没;持久要写 fstab ===
# 但 fstab 写错的代价,是整台机器开不了机。

# === 2. ★ fstab 里永远用 UUID,永远不用 /dev/sdX ===
$ blkid /dev/sdb1               # 查 UUID
# 设备名 sda/sdb 是临时编号,会变。

# === 3. ★ 数据盘那行一定加 nofail ===
UUID=...  /data  ext4  defaults,nofail  0 2
# 没 nofail,这块盘挂不上就能拖垮整个开机。

# === 4. ★ 改完 fstab 先 mount -a 验证,再重启 ===
$ mount -a
# 无报错才能重启 —— 这一条能挡掉绝大多数开机事故。

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

# === 6. 开机失败掉进 emergency mode 的自救 ===
$ mount -o remount,rw /         # 先让根分区可写
$ vi /etc/fstab                 # 修错误行
$ mount -a                      # 验证

# === 7. umount 提示 busy,先找谁占着 ===
$ lsof /挂载点  /  fuser -m /挂载点

# === 8. 排查挂载问题的命令链 ===
$ lsblk -f                      # ① 有哪些盘/分区、UUID、挂在哪
$ blkid                         # ② 查设备的 UUID 和文件系统类型
$ findmnt                       # ③ 当前挂载树
$ cat /etc/fstab                # ④ 开机要挂的条目对不对
$ mount -a                      # ⑤ 验证 fstab 能否干净挂上
$ journalctl -xb | grep mount   # ⑥ 开机挂载失败看这里
# 按这个顺序,磁盘挂载问题基本能定位。

命令速查

需求                        命令
=============================================================
看有哪些盘/分区/挂载点      lsblk  /  lsblk -f
查设备 UUID 和文件系统类型   blkid /dev/sdb1
格式化分区                  mkfs.ext4 /dev/sdb1
临时挂载                    mount /dev/sdb1 /data
卸载                        umount /data
看当前所有挂载(树状)       findmnt
按 fstab 挂载所有条目        mount -a
emergency 里让根分区可写     mount -o remount,rw /
找出谁占着挂载点            lsof /data  /  fuser -m /data
看开机挂载失败日志           journalctl -xb | grep mount

口诀:fstab 用 UUID 不用 sdX -> 数据盘必加 nofail
      改完 fstab 先 mount -a 验证 -> 无报错再重启

避坑清单

  1. mount 命令只是当下挂载,重启就失效,持久挂载必须写 /etc/fstab
  2. fstab 里要用 UUID 或 LABEL,绝不要用 /dev/sdX,设备名是临时编号会变
  3. 数据盘那行一定加 nofail,否则这块盘挂不上会拖垮整个开机进 emergency
  4. 改完 fstab 务必先 mount -a 验证无报错,再重启,别直接重启赌运气
  5. 改 fstab 前先 cp 备份一份,出事好回滚
  6. fstab 六字段:设备/挂载点/类型/选项/dump/fsck,fsck 根分区填1其他填2
  7. 挂载选项多个用逗号连不能带空格,nofail/noatime/_netdev 各有用途
  8. emergency mode 自救:mount -o remount,rw / 让根可写,再改 fstab
  9. umount 提示 target is busy,用 lsof 或 fuser 找出占用进程
  10. 挂载点目录原有内容会在挂载期间被遮盖,挂载前确认该目录是空的

总结

这次"挂个数据盘把整台服务器搞到开不了机"的事故,纠正了我一个关于"挂载"这件事的、相当致命的轻视。在这次之前,我把"给服务器挂一块盘"看成一件再简单不过的小事:mount 一下,盘就挂上了,能读能写;再往 /etc/fstab 里补一行,让它开机自动挂——在我心里,这后半步,不过是"把刚才那条 mount 命令,换个地方记下来"而已,是一件无足轻重的、抄写性质的收尾工作。正是这份轻视,让我在敲那行 fstab 时毫不上心:凭记忆写,用了 /dev/sdb1 这个"此刻看起来没错"的设备名,不加任何保险选项,看一眼"挺像样"就保存了。我完全没意识到,我刚刚埋下的,是一颗会在下一次重启时引爆的雷。复盘到根上,我才真正理解,mount 命令和 /etc/fstab,虽然都关于"挂载",却是性质完全不同的两件事——mount 管的是"现在":它把盘挂上,这个效果只活在当前这次开机的运行时里,机器一重启就烟消云散;而 fstab 管的是"以后":它是一份会被系统在【每一次开机】时都郑重读取、并逐行执行的"启动契约"。用一个只对"现在"有效的、临时的设备名 sdb1,去填写一份关乎"以后每次开机"的长期契约,这本身就是一个根本性的错配。因为磁盘的设备名——sdasdbsdc——根本不是磁盘的固有属性,它只是内核在每次开机时,按发现磁盘的先后顺序,临时派发的一个编号。这次它叫 sdb1,下次开机,只要识别顺序有一点变化,它就可能改叫 sdc1。我那行 fstab,等于把整台机器能否正常开机,赌在了一个注定会变的名字上。而比"用错设备名"更深、也更致命的一层认知盲区是:我从来不知道,fstab 里的一个条目,默认竟然是开机流程的一个【强依赖】。在我天真的想象里,一块数据盘挂载失败,顶多就是"那个目录暂时没法用"这么个局部的小麻烦。可 systemd 的逻辑完全不是这样:只要 fstab 里任何一个条目挂载失败,它就会判定"本地文件系统没有准备就绪",进而认为系统不具备正常启动的条件,于是干脆中止整个启动流程,把机器扔进 emergency mode。也就是说,我那块小小的、只用来存数据的盘,因为被我写进了 fstab 又没做任何防护,竟然被赋予了"一票否决整台服务器开机"的权力。想清楚这两层,正确的做法也就清晰得无可辩驳了。第一,fstab 里的设备,永远要用 UUID——那是文件系统在格式化时就被写入的、全局唯一且终身不变的"身份证",盘插在哪个口、设备名怎么变,UUID 都岿然不动。第二,也是这次的救命一课:数据盘那一行,必须加上 nofail 选项——它的含义是"这个盘万一开机挂不上,就跳过它,不要阻塞启动";加了它,即便挂载失败,系统也只是少了个 /data 目录,照样能正常开机,我登进去从容修复就是。一块数据盘的挂载成败,绝不该拥有否决整台机器开机的权力,而 nofail 就是收回这项过度权力的那把钥匙。第三,改完 fstab 之后,在重启之前,一定要先跑一遍 mount -a——它会按 fstab 把所有条目都试挂一遍,干净通过,才说明这份契约是对的、重启是安全的。这次从一个"挂个盘怎么会开不了机"的错愕出发,我最大的收获,是彻底改掉了对 /etc/fstab 的轻视——它不是一个随手抄写命令的备忘录,它是一份系统在每次开机时都会严格兑现、且默认拥有"否决开机"权力的契约。往这份契约里写东西,要像签一份正式合同一样:用稳定的标识(UUID),加上必要的免责条款(nofail),并且在生效前反复核验(mount -a)。一行随手写下的 fstab,和一台开不了机的服务器之间的距离,远比我曾经以为的,要近得多。

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

kill -9 用习惯了搞坏了数据:一次 Linux 信号与优雅关闭排查复盘

2026-5-20 19:20:40

Linux教程

压测 QPS 上不去服务却不忙:一次 Linux 内核参数 sysctl 调优排查复盘

2026-5-20 19:28:15

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