重启后新盘数据"蒸发"了:一次 Linux 磁盘挂载与 fstab 排查复盘

新数据盘挂到 /data 用了一个月,机房重启后数据库起不来、/data 空了。排查梳理:块设备/分区/文件系统/挂载点的关系、分区与 mkfs、mount 为何是临时挂载、/etc/fstab 字段详解与为何必须用 UUID、fstab 写错进 emergency mode 的排查,以及一套挂载管理纪律。

2024 年我给一台服务器加了块新数据盘,挂到 /data 上,把数据库的数据目录迁了过去。我用 mount 命令挂好,验证服务一切正常,心满意足地下班了。一个多月相安无事,直到机房一次例行重启。重启回来,数据库起不来,日志报 /data 目录里空空如也——我精心迁过去的数据"不见了"。我当时冷汗都下来了,以为新盘坏了。后来才查明白:数据一直好好地躺在新盘上,只是那块盘在重启后没有被挂载。我当初用 mount 挂的,是一次性的、临时的挂载,机器一重启就烟消云散,而我从来没有把它写进 /etc/fstab。这件事逼着我把磁盘、分区、文件系统、挂载这一整套彻底理清了。本文复盘这次实战。

问题背景

环境:CentOS 7,给服务器加了块新数据盘
事故现象:
- 一个多月前:新盘挂到 /data,迁了数据库数据目录,一切正常
- 机房重启后:数据库起不来,/data 是空的
- 我以为盘坏了 —— 实际上数据好好的,只是盘没被挂载

现场排查:
# 1. 看磁盘和挂载情况
$ lsblk
NAME   SIZE TYPE MOUNTPOINT
sda     50G disk
└─sda1  50G part /
sdb    200G disk            # ★ 新盘 sdb 在这,但 MOUNTPOINT 是空的!
                            #   它根本没被挂载到 /data

# 2. /data 现在是什么
$ df -h /data
文件系统  挂载点
/dev/sda1  /                # ★ /data 落在【系统盘】上,是个空的普通目录
                            #   不是那块 200G 的新盘

# 3. 手动挂回去看看数据在不在
$ mount /dev/sdb1 /data
$ ls /data
mysql/  ...                 # ★ 数据全在!松一口气 —— 盘没坏

# 4. 看 fstab 里有没有这块盘
$ cat /etc/fstab
UUID=xxxx  /      xfs  defaults  0 0
# —— 只有根分区,【根本没有 sdb 的任何记录】

根因(后来想清楚的):
我当初是用 `mount /dev/sdb1 /data` 挂上去的。
mount 命令的效果是【即时但临时】的 ——
它只改变当前这一刻系统的挂载状态,不写任何配置文件。
机器一重启,内核重新按 /etc/fstab 来挂载,
fstab 里没有这块盘 -> 它就不会被挂上 ->
/data 又变回系统盘上那个空目录。
数据没丢,是"挂载"丢了。

修复 1:块设备、分区、文件系统、挂载点

# === 一块盘要能用,要走完四步,缺一不可 ===
# 物理磁盘 -> 分区 -> 文件系统 -> 挂载点
#  (sdb)    (sdb1)   (xfs/ext4)   (/data)

# === 1. 块设备:一整块物理/虚拟磁盘 ===
# 命名:sda、sdb、sdc...(SCSI/SATA),vda(虚拟化),nvme0n1(NVMe)
$ lsblk
NAME   SIZE TYPE MOUNTPOINT
sda     50G disk            # 第一块盘
├─sda1   1G part /boot
└─sda2  49G part /
sdb    200G disk            # 第二块盘(还没分区)

# === 2. 分区:把一块盘切成几段 ===
# 分区后才有 sdb1、sdb2... 分区是文件系统的"容器"。

# === 3. 文件系统:在分区上"格式化"出来的组织结构 ===
# 常见:xfs(CentOS 7 默认)、ext4、btrfs。
# 没有文件系统的分区,就是一段原始空间,存不了文件。

# === 4. 挂载点:把文件系统"接"到目录树的某个位置 ===
# Linux 没有 C 盘 D 盘,所有东西都在【一棵目录树】上。
# 把 sdb1 这个文件系统挂到 /data,
# 此后访问 /data,访问的就是 sdb1 这块盘。

# === 几个查看命令 ===
$ lsblk                  # 树状看所有块设备 + 挂载点(最直观)
$ lsblk -f               # 多看文件系统类型和 UUID
$ df -hT                 # 看已挂载的文件系统:用量 + 类型
$ blkid                  # 看每个分区的 UUID 和文件系统类型
$ fdisk -l               # 看磁盘分区表的详细信息
$ findmnt /data          # 看某个挂载点的来龙去脉

修复 2:给新盘分区、建文件系统

# === 一块全新的盘 sdb,从零到能用 ===

# === 第一步:分区 ===
# 小于 2TB,可用 fdisk(MBR);大于 2TB 必须用 parted(GPT)。
$ fdisk /dev/sdb
# 进入交互:n(新建分区)-> p(主分区)-> 回车用默认 ->
#           w(写入并退出)
# 完成后会多出 /dev/sdb1

# 大盘用 parted(GPT):
$ parted /dev/sdb
(parted) mklabel gpt
(parted) mkpart primary 0% 100%
(parted) quit

# === 让内核重新读分区表(有时需要)===
$ partprobe /dev/sdb
$ lsblk         # 确认 sdb1 出现了

# === 第二步:建文件系统(格式化)===
# ★ 这一步会【清空】分区上的数据,务必确认设备名没写错!
$ mkfs.xfs  /dev/sdb1          # 建 xfs 文件系统(CentOS 7 推荐)
# 或:
$ mkfs.ext4 /dev/sdb1          # 建 ext4

# === 第三步:确认结果 ===
$ blkid /dev/sdb1
/dev/sdb1: UUID="abcd-1234-..." TYPE="xfs"
# ★ 把这个 UUID 记下来 —— 修复 4 写 fstab 要用它。

# === 给文件系统加个卷标(可选,方便辨认)===
$ xfs_admin -L data /dev/sdb1        # xfs 设卷标
$ e2label /dev/sdb1 data             # ext4 设卷标

# === 大盘 / LVM 的提示 ===
# 如果以后还想扩容,建议用 LVM(逻辑卷)而不是裸分区:
# pvcreate -> vgcreate -> lvcreate,扩容时 lvextend + xfs_growfs。
# 裸分区扩容很麻烦,规划阶段就该想清楚。

修复 3:mount——即时,但只是临时的

# === mount:把文件系统挂到目录树上 ===
$ mkdir -p /data                    # 挂载点目录要先存在
$ mount /dev/sdb1 /data             # 把 sdb1 挂到 /data
$ df -h /data                       # 确认:/data 现在是 sdb1 了

# === ★ 这次事故的核心:mount 是【临时】的 ===
# mount 命令做的事,只是改变【当前运行中的系统】的挂载状态。
# 它【不写任何配置文件】。
# 机器一重启,内核会重新按 /etc/fstab 从头挂载一遍,
# 你之前 mount 的那一下,早就随着上次关机灰飞烟灭了。
# —— 这就是为什么我的 /data 重启后"空了"。

# === 挂载时常用的选项 ===
$ mount -t xfs /dev/sdb1 /data       # -t 指定文件系统类型
$ mount -o ro /dev/sdb1 /mnt         # -o ro 只读挂载
$ mount -o noatime /dev/sdb1 /data   # noatime 不记录访问时间,省 IO

# === 卸载 ===
$ umount /data
$ umount /dev/sdb1                   # 用设备名或挂载点都行

# === umount 报 "target is busy" 怎么办 ===
$ umount /data
umount: /data: target is busy
# 说明还有进程在用这个目录。先找出是谁:
$ lsof +D /data            # 列出在 /data 下打开文件的进程
$ fuser -m /data           # 同样能列出占用的进程
# 处理掉那些进程,或先把服务停掉,再 umount。
# ★ 别动不动用 umount -l(惰性卸载),它会掩盖问题。

# === 看当前所有挂载 ===
$ mount                    # 列出所有挂载(信息较杂)
$ findmnt                  # 树状显示,清爽得多

修复 4:/etc/fstab——让挂载持久化

# === 治本:把挂载写进 /etc/fstab,开机自动挂 ===
# /etc/fstab 是开机时内核/systemd 用来挂载文件系统的"清单"。
$ vim /etc/fstab

# === fstab 每一行 6 个字段 ===
# <设备>            <挂载点>  <类型>  <选项>            
UUID=abcd-1234-...  /data     xfs     defaults         0      0

# 字段逐个解释:
# 1 设备   ★ 强烈建议用 UUID,别用 /dev/sdb1(见下)
# 2 挂载点 挂到目录树的哪里(目录要先存在)
# 3 类型   xfs / ext4 / nfs ...
# 4 选项   defaults 是一组常用默认值;可加 noatime、nofail 等
# 5 dump   是否被 dump 备份工具处理,一般填 0
# 6 fsck   开机自检顺序:根分区填 1,其他填 2,不检填 0

# === ★ 为什么必须用 UUID,不用 /dev/sdb1 ===
# 设备名(sda/sdb)是内核【按发现顺序】分配的,不固定!
# 你加了块盘、换了 HBA、改了 BIOS 顺序,
# 原来的 sdb 可能就变成了 sdc。
# fstab 里写死 /dev/sdb1,设备名一变 -> 挂载就错位甚至失败。
# UUID 是文件系统的"身份证",建文件系统时生成,跟着盘走,不会变。
$ blkid /dev/sdb1          # 拿 UUID
$ vim /etc/fstab           # 用 UUID=... 写进去

# === ★ 改完 fstab,务必当场用 mount -a 验证 ===
$ mount -a
# mount -a:按 fstab 把"还没挂的"都挂上。
# 如果 fstab 写错了,这一步【立刻报错】——
# 这远比"重启之后才发现进不去系统"安全一万倍。
$ df -h /data             # 确认 /data 挂上了

# === 给"非关键盘"加 nofail,避免拖垮开机 ===
UUID=abcd-...  /data  xfs  defaults,nofail  0 2
# nofail:这块盘万一挂不上(盘坏了、拔了),
# 系统【跳过它继续启动】,不会卡在开机界面。
# ★ 数据盘强烈建议加 nofail。

修复 5:fstab 写错导致开机失败的排查

# === fstab 写错的后果:轻则少挂个盘,重则【开不了机】===
# 如果某行写错(UUID 错、类型错、且没加 nofail),
# 开机时挂载失败,系统会进入 "emergency mode"(紧急模式),
# 卡在一个要求输入 root 密码的救援 shell。

# === 进了 emergency mode,怎么救 ===
# 1. 输入 root 密码,进入救援 shell
# 2. 此时根文件系统通常是【只读】的,先重新挂成可读写:
$ mount -o remount,rw /
# 3. 把 fstab 改回去(注释掉出错的那行)
$ vim /etc/fstab
# 4. 验证改对了:
$ mount -a            # 不再报错,才算改好
# 5. 重启
$ reboot

# === 怎么从根上避免进 emergency mode ===
# 铁律:改完 fstab,【重启前】一定先 mount -a。
# mount -a 通过了,才说明 fstab 这几行是对的。
# 这一条能挡掉几乎所有"fstab 写错开不了机"的事故。

# === systemd 时代的验证手段 ===
$ systemctl daemon-reload          # 让 systemd 重新读 fstab
$ findmnt --verify                 # ★ 校验 fstab 语法/字段是否合法
$ findmnt --verify --verbose       # 更详细
# findmnt --verify 能在不重启的情况下,
# 提前发现 fstab 里的错误。

# === 排查"某块盘开机没挂上" ===
$ systemctl --failed               # 看有没有 mount 相关的 failed 单元
$ journalctl -b | grep -i mount    # 看本次开机的挂载日志
$ dmesg | grep -i -E 'sdb|xfs|ext4'  # 看内核有没有报盘的错

# === 临时排错:先用设备名挂上救急,再回头修 fstab ===
$ mount /dev/sdb1 /data            # 先让服务能跑
$ blkid /dev/sdb1                  # 再拿正确 UUID 修 fstab

修复 6:磁盘挂载管理纪律

# === 这次事故暴露了挂载管理的随意,定几条纪律 ===

# === 1. ★ 第一纪律:mount 是临时的,要持久必须写 fstab ===
# 任何"希望重启后还在"的挂载,都【必须】落进 /etc/fstab。
# 只 mount 不写 fstab = 给未来的某次重启埋了颗雷。

# === 2. fstab 里一律用 UUID,不用 /dev/sdX ===
# 设备名会变,UUID 不会。blkid 拿 UUID,写进 fstab。

# === 3. 改完 fstab,重启前必须 mount -a + findmnt --verify ===
# 这是不进 emergency mode 的唯一保证。没验证过,别重启。

# === 4. 数据盘加 nofail,别让一块坏盘拖垮整机启动 ===
UUID=...  /data  xfs  defaults,nofail  0 2

# === 5. 格式化前,把设备名核对三遍 ===
# mkfs 是不可逆的清空操作。
$ lsblk            # 反复确认:我要格式化的,确实是那块【空的新盘】
# 把 mkfs.xfs /dev/sdb1 看成"清空 sdb1",敲回车前再确认一次。

# === 6. 迁数据到新盘,验证流程要完整 ===
# ① mount 新盘到临时点 -> ② 拷数据 -> ③ 校验数据完整 ->
# ④ 写 fstab -> ⑤ mount -a 验证 -> ⑥ ★ 主动 reboot 一次,
#    确认重启后挂载、服务都正常 —— 别等机房重启时才发现问题。

# === 7. 定期巡检挂载状态 ===
$ df -hT                  # 各文件系统用量、类型,是不是都在
$ findmnt                 # 挂载树是否符合预期
$ lsblk                   # 有没有"有盘但没挂载"的情况
# 把"加盘 -> 写 fstab -> 重启验证"做成固定 checklist。

命令速查

需求                        命令
=============================================================
树状看所有盘和挂载          lsblk  /  lsblk -f
看已挂载文件系统用量        df -hT
看分区 UUID 和类型          blkid
给盘分区(小盘)            fdisk /dev/sdb
建文件系统(会清空数据)    mkfs.xfs /dev/sdb1
临时挂载                    mount /dev/sdb1 /data
卸载                        umount /data
查谁占用了挂载点            lsof +D /data  /  fuser -m /data
持久化挂载                  写 /etc/fstab(用 UUID)
★ 改完 fstab 验证           mount -a  +  findmnt --verify
看挂载相关开机日志          journalctl -b | grep -i mount

口诀:mount 只是临时 -> 要持久必写 fstab(UUID+nofail)
      -> 改完 fstab 重启前必 mount -a 验证

避坑清单

  1. mount 命令的挂载是临时的,只改当前状态不写配置,重启即失效
  2. 要让挂载在重启后还在,必须把它写进 /etc/fstab
  3. fstab 里用 UUID 而不是 /dev/sdX,设备名按发现顺序分配会变
  4. blkid 拿分区 UUID,新建文件系统时 UUID 生成后跟着盘走不变
  5. 改完 fstab 重启前必须 mount -a,写错会立刻报错而不是开不了机
  6. findmnt --verify 能不重启就校验 fstab 语法和字段是否合法
  7. 数据盘在 fstab 选项里加 nofail,坏盘也不会卡住整机启动
  8. fstab 写错且没 nofail 会让系统进 emergency mode,需 remount,rw 修复
  9. mkfs 格式化会清空分区数据不可逆,执行前用 lsblk 核对设备名三遍
  10. 迁数据到新盘后要主动 reboot 一次验证,别等机房重启才暴露问题

总结

这次新盘"数据蒸发"的虚惊,纠正了我一个潜藏很深的错误直觉:我一直以为,只要我用 mount 把一块盘挂上了、服务也跑起来了,这件事就算"做完了"、是"稳定的"了。这次重启狠狠地教育了我——一个挂载,只要它没有被写进 /etc/fstab,那它就不是一个"完成态",而是一个随时会在下一次重启时消失的"临时态"。复盘到最后,真正的关键,是我终于想清楚了 mount 命令和 /etc/fstab 这两者职责上的根本分野。mount 命令做的事情,是"即时"的,但也仅仅是即时的——它改变的,只是此时此刻这个正在运行的系统的挂载状态,它在内核当前的内存里登记了一笔"sdb1 现在挂在 /data",但它不会、也从来不负责把这件事记录到任何一个会被持久保存的配置文件里去。而 /etc/fstab 才是那个"清单"——每一次开机,内核和 systemd 都会老老实实地、从头到尾地读一遍 fstab,严格按照这份清单上写明的内容,把一个个文件系统挂载到目录树上。这两件事之间,没有任何自动的桥梁:我用 mount 命令临时挂上的东西,绝不会神奇地、自动地"流"进 fstab。所以当机房那次重启发生时,内核做的事情再正常不过——它读了一遍 fstab,而 fstab 里压根没有那块新盘的任何记录,于是它就理所当然地没有去挂载它;/data 于是又退回成了系统盘上那个我当初创建的、空荡荡的普通目录。数据从来没有丢,丢的是"挂载"这个动作本身,因为它从一开始就只是个临时状态,而我误以为它是永久的。想通了这一层,我才真正理解了为什么 fstab 这份清单需要被如此严肃地对待,以及它里面那几个看似枯燥的字段,每一个背后都是一条用事故换来的经验。其中我体会最深的,是为什么强烈建议在 fstab 里用 UUID 来标识一块盘,而不是用 /dev/sdb1 这样的设备名。设备名 sda、sdb、sdc,是内核在开机扫描硬件时,按它"发现"这些盘的先后顺序临时分配的,这个顺序并不被任何东西保证——我哪天再加一块盘、换一下硬件、动一下 BIOS 里的顺序,今天的 sdb 完全可能在下次开机时变成 sdc。如果 fstab 里写死的是 /dev/sdb1,那么设备名一旦漂移,这一行要么挂载到了错误的盘上,要么干脆挂载失败。而 UUID 不一样,它是文件系统在被创建出来的那一刻就生成的、独一无二的"身份证",它牢牢地跟着这个文件系统本身走,无论这块盘被插在哪个口、被内核叫做 sd 几,它的 UUID 永远不变。另一条用代价换来的纪律,是改完 fstab、在重启之前,必须先用 mount -a 跑一遍来验证。因为 fstab 写错的后果可以非常严重——如果某一行写错了、对应的盘又没有加 nofail 选项,系统在开机挂载它失败时,会直接掉进 emergency mode,卡在一个要求输入 root 密码的救援 shell 里,整台机器都起不来。而 mount -a 这个命令,会立刻按照 fstab 的内容尝试把还没挂的都挂上,fstab 里要是有错,它当场就报出来——在一个还能正常操作的系统里看到报错并从容改正,比在一台开不了机的服务器面前手忙脚乱,要安全和体面太多了。这次从一场虚惊出发,我最大的收获,是把"挂载一块盘"这件事,从我脑海里那个"敲一下 mount 就完事"的单一动作,彻底重新理解成了一条必须完整走完的链路:分区、建文件系统、临时挂载验证、写进 fstab、用 mount -a 验证、再主动重启确认一次——只有这最后一次主动的重启平安通过了,这块盘才算真正地、可靠地"安顿"了下来。

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

用 ln 做的"备份"凭空蒸发了:一次 Linux 软硬链接排查复盘

2026-5-20 18:06:28

Linux教程

chmod 777 埋下的木马:一次 Linux 文件权限排查复盘

2026-5-20 18:14:28

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