发布时间:2026-09-22 12:31 更新时间:2026-09-22 12:31 阅读量:0
很多人在服务器上加一块数据盘,第一反应是照着教程往 /etc/fstab 里写一行,然后 reboot。结果 SSH 连不上、控制台一看卡在 emergency mode,或者屏幕上滚动着 "Dependency failed for Local File Systems"。这类故障几乎全部来自同一处配置文件的写法,而且绝大多数情况下数据盘本身并没有坏,只是系统在启动阶段找不到你写的那块盘,于是整个挂载流程被卡住。本文讲清楚为什么会卡、UUID 和设备名有什么区别、nofail 到底解决什么问题,以及在救援模式下怎么把系统救回来。
systemd 在启动过程中要完成 local-fs.target,这个 target 会按 /etc/fstab 里的条目逐条挂载。关键在于:如果某条挂载项对应的设备不存在、UUID 写错,或者文件系统损坏无法挂载,systemd 默认会认为这个 target 失败。而 local-fs.target 是很多服务的前置依赖,失败后系统不会进入正常的多用户模式,而是掉进 emergency mode,要求你输入 root 密码做修复。SSH 服务此时通常还没起来,所以只能走 VNC、IPMI、云厂商的 VNC 控制台这类带外通道。
反过来理解就清楚了:不是 fstab 里某一行写错导致系统崩溃,而是这一行的挂载失败被 systemd 当成硬性依赖没满足,从而中断了整个启动流程。所以修复思路有两个方向,一是把配置改对,二是让这一行的失败不再阻塞启动。
第一个坑是 UUID 与设备名混用。像 /dev/sdb1 这种设备名在启动时由内核按探测顺序分配,换一块硬盘、改一次 BIOS 启动顺序、插拔一次 RAID 卡,sdb 就可能变成 sdc。而 UUID 是文件系统创建时写入超级块的标识,跟着文件系统走,不受插槽和顺序影响。长期稳定的挂载项应该用 UUID 或 LABEL,设备名只适合临时调试。
# 查看块设备及其文件系统 UUID(推荐用 lsblk 顺带看挂载点)
lsblk -f
也可以只看某个设备的 UUID
blkid /dev/sdb1
查看当前已挂载项,确认实际生效的挂载参数
findmnt --verify
findmnt -o TARGET,SOURCE,FSTYPE,OPTIONS
拿到 UUID 后,fstab 的写法是 UUID=xxxx-xxxx 后面接挂载点、文件系统类型和参数。注意 UUID 里的连字符和大小写要原样复制,手敲很容易漏一位。
第二个坑是 没有 nofail。对于非系统盘的数据盘,加上 nofail 表示即使这块盘不存在或挂载失败,也不阻塞启动流程,系统照样进多用户模式,你还能 SSH 上去处理。与之配套的还有 x-systemd.device-timeout,可以给设备出现设一个等待上限,避免某些云盘、iSCSI 盘在启动时长时间等待。下面是几种常见写法对比。
# 系统盘:必须挂载成功,不加 nofail
UUID=1111-2222 / ext4 defaults 0 1
数据盘:允许失败,不阻塞启动
UUID=aaaa-bbbb /data ext4 defaults,nofail,x-systemd.device-timeout=10 0 2
网络存储:等待时间更长,且允许失败
UUID=cccc-dddd /backup ext4 defaults,nofail,x-systemd.device-timeout=30 0 2
第三个坑是 nofail 被误用在根分区或 /usr 上。根文件系统挂不上,系统本来也就没法运行,加 nofail 没有意义,反而掩盖真实故障。另外 fstab 最后两列(dump 和 fsck 顺序)也要注意,根分区一般写 0 1,其它 ext4 分区写 0 2,非 ext 文件系统通常写 0 0。
系统已经卡在 emergency mode 时,控制台一般会提示输入 root 密码进入维护 shell。如果连这个提示都没有,可以在 GRUB 菜单里选中内核条目,按 e 编辑启动参数,在 linux 那一行末尾加上 rd.break 或 systemd.unit=emergency.target 进入救援环境。进入后如果根文件系统是只读的,先重新挂载为可写。
# 进入维护 shell 后,若根为只读,先重挂为可写
mount -o remount,rw /
查看当前 fstab,定位写错的那一行
cat /etc/fstab
备份原文件再修改,避免改坏后无法回退
cp /etc/fstab /etc/fstab.bak
vi /etc/fstab
校验 fstab 语法与挂载可行性(部分系统需 root 权限)
findmnt --verify
尝试手动挂载被改动的条目,确认参数正确
mount /data
确认无误后重启
systemctl reboot
修改时优先把设备名改成 UUID,给非系统盘补上 nofail。如果暂时查不到 UUID,也可以先用 LABEL 或者设备名临时挂载,等系统起来再规范化。重启前建议多看一眼 /etc/fstab 的空白字符,Tab 和空格混用、行尾多余字符都可能让解析出错。
如果系统能正常启动但某块盘没挂上,先别急着改 fstab,用 dmesg 和 journalctl 看内核报错,常见原因是文件系统类型写错、挂载点目录不存在、或者文件系统有错误需要 fsck。挂载点目录必须先存在,fstab 不会帮你创建目录。
# 查看本次启动中与挂载相关的报错
dmesg | grep -i -E 'mount|ext4|xfs' | tail -n 30
journalctl -b -u '*.mount' --no-pager | tail -n 50
检查挂载点目录是否存在
ls -ld /data
检查文件系统是否需要修复(卸载状态下执行,操作前请确认已备份)
fsck -n /dev/sdb1
需要提醒的是,fsck 对已挂载或在用的文件系统执行是有风险的,生产环境务必先确认设备未被挂载、数据已有备份,具体参数以对应文件系统的官方文档为准。
fstab 出问题之所以吓人,是因为它发生在启动早期,带外通道又常常要现找。把习惯改一改就能避开大部分事故:能用 UUID 就不写设备名;非系统盘一律加 nofail;改完先执行 findmnt --verify 或 mount -a 验证,确认无误再重启;重要变更前先 cp /etc/fstab /etc/fstab.bak 留一份备份。云服务器建议在控制台确认 VNC 或串口登录可用,再动 fstab 这类启动相关配置。这样即使某次写错,也能从带外控制台从容进救援模式改回来,不至于把一次加盘操作变成一次数据恢复演练。
| 📑 | 📅 |
|---|---|
| MySQL备份文件损坏怎么验证:一致性校验与恢复演练 | 2026-09-22 |
| Nginx WebSocket 与 SSE 并存:proxy_buffering 冲突排查 | 2026-09-22 |
| Linux磁盘IO高却查不出:iotop与blkio限速实战 | 2026-09-22 |
| 服务器被DDoS打满带宽:自查连接分布与限速缓解 | 2026-09-22 |
| Nginx 代理 WebSocket 频繁断连:Upgrade 头、超时与保活配置 | 2026-09-22 |
| Nginx 反代下 Cookie 域与 Path 错乱排查实战 | 2026-09-23 |
| MySQL单表过亿后的分页优化:延迟关联与覆盖索引 | 2026-09-23 |
| Docker 容器启动即退出排查:exit code、logs 与前台进程 | 2026-09-23 |
| Linux 服务器 CPU 软中断 si 偏高排查:网卡多队列、RPS 与内核参数调整 | 2026-09-23 |
| Nginx客户端与后端长连接谁在复用:端口耗尽排查顺序 | 2026-09-23 |