跳转至

磁盘突变 Read-only

01 前置理论与核心机制

1. 操作禁忌:盲目重启

  • 失联风险:遇到 Read-only file system 报错时,严禁直接执行 reboot 重启服务器。若底层文件系统结构已损坏,盲目重启会导致系统在开机自检(fsck 阶段)时卡住无法进入操作系统,导致远程 SSH 彻底失联。
  • 抢救窗口期:文件系统变为只读状态时,虽然无法写入新数据,但存量数据通常依然可读。这是排查故障根因和备份核心数据的关键时间窗口。

2. 只读锁定的触发机制

  • 内核保护机制:磁盘变为只读,通常是因为挂载参数中配置了 errors=remount-ro(许多发行版的默认配置)。当操作系统内核检测到异常断电导致的日志(Journal)不一致、索引节点(Inode)元数据错乱或底层硬件 I/O 报错时,为防止错乱的数据进一步覆盖磁盘导致永久损坏,内核会主动将该文件系统降级挂载为只读(Read-only)模式。

02 故障排查与恢复闭环 SOP

当创建文件或修改配置提示 Read-only file system 时,按以下标准链路进行定界与恢复:

步骤一:提取内核日志定界故障原因

直接调取内核环形缓冲区的报错日志,区分是文件系统逻辑错乱还是硬件物理损坏:

# 查看内核日志,重点关注磁盘与文件系统报错类型
dmesg -T | tail -n 30
  • 观测点 A (逻辑故障):若日志报错为 EXT4-fs error 或 XFS internal error,且无底层扇区报错,说明物理磁盘正常,仅是文件系统目录树或 Inode 索引元数据不一致,可通过文件系统的修复工具恢复。
  • 观测点 B (物理故障):若日志持续输出 I/O error、Medium Error 或 blk_update_request: I/O error,说明物理硬盘出现了坏道或存储链路故障。此时严禁执行 fsck 修复操作,应立即转入数据跨机备份流程。

步骤二:卸载故障分区 (umount)

确认为逻辑故障后,必须先将故障分区卸载,才能安全执行文件系统检查与修复:

umount /data
  • 占用处理:若提示 target is busy(目标繁忙),说明仍有进程正在访问该目录。需先停止相关业务服务,或执行 fuser -m -v -k /data 终止所有占用该挂载点的进程后再执行卸载。

步骤三:执行文件系统逻辑修复 (高危操作)

卸载成功后,使用对应的文件系统修复工具对块设备进行元数据一致性修复。 - 操作风险提示:严重的元数据损坏在修复过程中,可能会导致部分无法关联目录树的孤立数据块被移入 lost+found 目录。针对生产环境核心数据盘,执行修复前务必先在云平台或存储层创建磁盘快照!

# 针对 ext3/ext4 文件系统:-y 参数表示自动确认所有修复项
fsck.ext4 -y /dev/sdb

# 注意:若为 CentOS 7+ 默认的 XFS 文件系统,需使用专用的 xfs_repair 工具:
# xfs_repair /dev/sdb
等待修复进度完成,终端提示文件系统已修正(File system was modified)。

步骤四:重新挂载与读写验证

修复完成后,将磁盘重新挂载回原目录并验证读写功能:

mount /dev/sdb /data

# 验证读写是否恢复正常
touch /data/test_write.txt && rm -f /data/test_write.txt

03 真实生产故障现象与案例库

案例 1:异常断电导致 Inode 元数据不一致

  • 故障现象:机房意外断电重启后,某台业务服务器上的 /data 分区变为只读状态,应用写入日志全部报错。
  • 排查与处置:执行 dmesg -T 显示 EXT4-fs error (device sdb): ext4_lookup: deleted inode referenced,未见硬件 I/O 报错。停止相关应用进程后,执行 umount /data 与 fsck.ext4 -y /dev/sdb。修复耗时约 5 分钟,重新挂载后业务读写恢复正常。

案例 2:云盘底层存储网络抖动触发只读保护

  • 故障现象:云主机挂载的数据盘突发只读报错,但主机并未发生重启或断电。
  • 排查与处置:检查 dmesg 发现某时间点短暂出现了数条 I/O error,紧接着输出 Remounting filesystem read-only。原因为云厂商底层分布式存储网络发生瞬断,触发了操作系统的只读保护机制。由于云盘底层链路已自动恢复,卸载(umount)后重新挂载(mount)即恢复正常读写,无需执行 fsck。

案例 3:物理硬盘坏道引发只读锁定

  • 故障现象:某物理服务器上的数据库停止响应并报 Read-only,dmesg 高频输出 I/O error, dev sdc, sector 2345102。
  • 排查与处置:确认为物理硬盘出现介质坏道。此时严禁执行 fsck,否则高频的磁盘扫描读写会加速磁头与盘片损坏,导致整块硬盘彻底离线。利用当前只读模式仍可读取数据的窗口期,立即在备用服务器上执行 rsync -avz root@<故障IP>:/data/ /backup/ 将核心数据跨机同步备份,随后下线故障机并更换物理硬盘。

04 生产排障速查表(Read-only 突发故障)

排查阶段执行命令 / 观测点定性分析标准处置动作01 原因定界dmesg -T | tail -n 30区分是文件系统报错还是 I/O error决定走逻辑修复还是物理数据抢救02 卸载分区umount <挂载点>若提示 target is busy 无法卸载停止业务或执行 fuser -m -k <挂载点> 释放占用03 逻辑修复fsck -y <设备> 或 xfs_repair扫描并修复损坏的 Inode 与目录树修复前先打快照,修复完成后重新 mount04 物理故障持续输出 I/O error / Medium Error物理硬盘坏道、线缆松动或阵列卡故障严禁执行 fsck,立即使用 rsync 跨机备份可读数据05 防御加固检查 /etc/fstab 挂载参数确认是否包含 errors=remount-ro确保异常时及时锁死只读,防止脏数据扩散覆盖

05 面试应答参考话术

面试官问:“线上运行正常的服务器,突然创建文件或修改配置都报错 Read-only file system。你怎么排查和恢复?”

可以这样回答:遇到 Read-only file system 报错,首要原则是不能盲目重启服务器。如果底层文件系统已经损坏,直接重启很容易卡在开机自检(fsck)阶段,导致服务器无法进入系统而彻底失联。磁盘变成只读是 Linux 内核的一种自我保护机制(通常由挂载参数 errors=remount-ro 触发),此时虽然无法写入,但数据依然可读。我会立刻执行 dmesg -T 查看内核日志,对故障原因进行定界:第一种情况:硬件物理故障。

如果 dmesg 日志里持续输出 I/O error 或扇区报错,说明硬盘出现了物理坏道或硬件故障。此时绝对不能执行 fsck 修复,否则高强度的扫描读写会导致硬盘彻底损坏。正确的做法是趁着只读状态还能读取数据,立即使用 rsync 将重要文件跨机备份出去,随后联系机房更换物理硬盘。第二种情况:文件系统逻辑错乱。

如果日志报的是 EXT4-fs error 或 XFS internal error,说明物理硬盘没坏,通常是异常断电或进程崩溃导致底层的 Inode 索引或日志元数据不一致。 此时按三步进行恢复: 第一步,将该分区 umount 卸载。如果提示 target is busy,就先停掉相关应用,或用 fuser -m -k 终止占用该目录的进程。 第二步,对核心数据盘先打一份快照做兜底,然后执行 fsck -y(如果是 XFS 文件系统则使用 xfs_repair)对块设备进行自动一致性修复。 第三步,修复完成后,重新执行 mount 将分区挂载回原目录,读写即可恢复正常。

06 面试高频追问与应答预案

追问 1:使用 fsck 修复完成后,发现部分原有的文件找不到了,它们去哪了?

  • 回答要点:
  • 文件系统在执行修复时,会将那些 Inode 索引关系断裂、找不到所属父目录的孤立数据块(Orphaned Inodes),统一移动到该挂载点根目录下的 lost+found 文件夹中。
  • 由于目录项信息丢失,这些文件原本的文件名通常已无法恢复,会被重命名为一串对应的 Inode 数字编号。若丢失了关键配置或数据文件,可进入 lost+found 目录,配合 file 命令识别文件类型,并用 grep 或 cat 检索内容进行人工找回。

追问 2:如果是系统的根分区 (/) 变成了 Read-only,无法直接执行 umount 卸载怎么办?

  • 回答要点:
  • 正在运行中的操作系统根分区被内核及系统进程强占用,无法直接执行 umount。
  • 若仅是偶发状态异常且底层无损坏,可尝试执行 mount -o remount,rw / 直接在线重新挂载为读写模式。若根分区确实存在文件系统元数据损坏需要执行 fsck,由于必须在卸载或只读未占用状态下修复,标准做法是通过云控制台 VNC 或物理机带外管理(IPMI/iDRAC),重启进入 救援模式(Rescue Mode) 或挂载 LiveCD 镜像,在脱离原根分区运行的环境下对其执行 fsck 或 xfs_repair 修复。

07 文件系统健康状态自动巡检脚本(check_fs_health.sh)

该脚本用于自动检测本机所有物理挂载点的读写状态,并从内核日志中检索是否存在文件系统逻辑错误或底层硬件 I/O 坏道告警。

#!/usr/bin/env bash
# ==============================================================================
# 脚本名称: check_fs_health.sh
# 功能描述: 文件系统读写状态检测与内核底层 I/O 错误自动化巡检 (纯只读)
# 使用方式: 在目标 Linux 宿主机以 root 权限执行
# ==============================================================================

set -o pipefail

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
PLAIN='\033[0m'

echo -e "${BLUE}================================================================${PLAIN}"
echo -e "${BLUE}           系统底层磁盘读写状态与 I/O 健康度安全巡检            ${PLAIN}"
echo -e "${BLUE}================================================================${PLAIN}"

# 1. 检查挂载点的 Read-only 状态
echo -e "\n${YELLOW}[1/3] 检查当前文件系统挂载读写状态...${PLAIN}"
# 修复了 awk 正则表达式中的管道符乱码
RO_MOUNTS=$(awk '$4 ~ /(^|,)ro(,|$)/ && $3 !~ /^(sysfs|proc|tmpfs|devtmpfs|squashfs|iso9660|overlay|pstore|efivarfs|cgroup.*|debugfs|tracefs|nsfs|fuse.*)$/ {print $1, $2, $3}' /proc/mounts)

if [ -n "$RO_MOUNTS" ]; then
    echo -e "  -> ${RED}[ALERT] 检测到处于只读 (Read-only) 状态的挂载点:${PLAIN}"
    echo "$RO_MOUNTS" | while read -r dev mountpoint fstype; do
        # 修复了输出字符串中的管道符乱码
        echo -e "     设备: ${YELLOW}${dev}${PLAIN} | 挂载点: ${RED}${mountpoint}${PLAIN} | 格式: ${fstype}"
    done
    echo -e "  -> ${YELLOW}[提示] 请立即结合下方 dmesg 检查结果定界是文件系统逻辑错误还是物理磁盘坏道。${PLAIN}"
else
    echo -e "  -> ${GREEN}[OK] 所有常规物理分区均处于正常读写 (rw) 状态。${PLAIN}"
fi

# 2. 从 dmesg 检索文件系统逻辑错误 (EXT4/XFS error)
echo -e "\n${YELLOW}[2/3] 检索内核日志中的文件系统逻辑错误...${PLAIN}"
FS_ERRORS=$(dmesg -T 2>/dev/null | grep -iE "EXT4-fs error|XFS internal error|XFS.*corruption|Remounting filesystem read-only" | tail -n 5)

if [ -n "$FS_ERRORS" ]; then
    echo -e "  -> ${RED}[WARN] 检测到文件系统逻辑报错或只读降级记录:${PLAIN}"
    echo -e "${YELLOW}${FS_ERRORS}${PLAIN}"
    echo -e "  -> ${GREEN}[处置建议] 若下方无硬件 I/O 报错,请创建磁盘快照后卸载对应分区,使用 fsck 或 xfs_repair 修复。${PLAIN}"
else
    echo -e "  -> ${GREEN}[OK] 未发现明显的 EXT4/XFS 文件系统元数据错误记录。${PLAIN}"
fi

# 3. 从 dmesg 检索底层物理硬件故障 (I/O error)
echo -e "\n${YELLOW}[3/3] 检索底层物理磁盘 I/O 错误与坏道告警...${PLAIN}"
IO_ERRORS=$(dmesg -T 2>/dev/null | grep -iE "I/O error|medium error|hard error|Buffer I/O error|blk_update_request" | tail -n 5)

if [ -n "$IO_ERRORS" ]; then
    echo -e "  -> ${RED}[DANGER] 检测到硬件级别的磁盘 I/O 报错,极可能存在物理坏道或存储链路故障:${PLAIN}"
    echo -e "${RED}${IO_ERRORS}${PLAIN}"
    echo -e "  -> ${YELLOW}[操作禁忌] 严禁对此磁盘执行 fsck 扫描!请立即使用 rsync 跨机备份可读数据并联系硬件运维换盘。${PLAIN}"
else
    echo -e "  -> ${GREEN}[OK] 未发现底层物理磁盘 I/O 报错记录。${PLAIN}"
fi

echo -e "\n${BLUE}================================================================${PLAIN}"
echo -e "${BLUE}巡检完毕。生产环境配置 /etc/fstab 时建议保留 errors=remount-ro 参数以防止脏数据扩散。${PLAIN}"
echo -e "${BLUE}================================================================${PLAIN}"