某天你登录服务器,发现往 /data 目录里写文件失败,报 Read-only file system;或者应用突然大量报错,日志里全是"无法写入"。df -h 看容量还剩很多,权限也对,但就是写不进去。这时候八成是文件系统被内核切成了只读模式。
磁盘变只读不是"磁盘满了",也不是权限问题,而是 Linux 内核的一种自我保护机制:当它检测到文件系统内部出现不一致(比如元数据损坏、块设备 I/O 错误、XFS 日志校验失败),为了避免损坏进一步扩大,会主动把文件系统重新挂载为只读。理解这一点很关键——变只读往往是"症状",根因可能在硬盘硬件、可能在文件系统本身、也可能在电源或线缆。
这篇文章会讲清楚:怎么确认是不是只读、怎么从日志里找到真正的触发原因、按 ext4 和 XFS 分别怎么修复、以及修复过程中哪些操作会直接毁数据。全程强调"先定位根因、再动手修复",因为盲目 fsck 有时比故障本身更危险。
一、先确认现象:是不是真的变成了只读
先确认三件事:挂载状态、内核日志、以及底层磁盘是否还健康。
# 1. 看挂载选项里有没有 ro
mount | grep -E "data|vdb"
# 输出里如果看到 (ro,relatime,...) 就说明是只读挂载
# 2. 查看具体挂载信息
findmnt /data
# 3. 查看内核日志里的文件系统错误(关键步骤)
sudo dmesg -T | grep -iE "error|corrupt|I/O error|remount|read-only|XFS|EXT4"
sudo journalctl -k -p err --since "2 hours ago"
# 4. 看系统日志
sudo tail -200 /var/log/messages # RHEL/CentOS/Rocky
sudo tail -200 /var/log/syslog # Debian/Ubuntu
日志里常见的触发信息有这么几类,对应不同根因:
| 日志关键词 | 含义 | 根因方向 |
|---|---|---|
EXT4-fs error ... Remounting filesystem read-only |
ext4 检测到不一致 | 文件系统损坏 |
XFS (...): Corruption detected |
XFS 元数据校验失败 | 文件系统损坏 |
XFS (...): log I/O error |
日志区读写失败 | 磁盘硬件/线缆 |
Buffer I/O error on dev vdb1 |
块设备层 I/O 错误 | 磁盘坏道/线缆/驱动 |
attempt to access beyond end of device |
访问越界 | 分区表损坏 |
ata ... failed command |
SATA 命令失败 | 硬盘或链路问题 |
如果日志里出现的是 Buffer I/O error 或 I/O error 这类底层错误,那问题很可能在硬件,此时先别急着修文件系统——盘本身坏了的话,修复没有意义,应该优先抢救数据。如果只有文件系统层的 corruption 而没有硬件 I/O 错误,则多半是掉电、非正常关机导致的元数据损坏,修复成功率高。
二、判断根因:硬件问题还是文件系统问题
# 查看磁盘 SMART 健康状态(需要 smartmontools)
sudo smartctl -H /dev/vdb
sudo smartctl -a /dev/vdb | grep -E "Reallocated|Pending|Uncorrectable|Power_On"
# 查看内核有没有报底层 ata/scsi 错误
sudo dmesg -T | grep -iE "ata[0-9]|scsi|sd[a-z]"
# 尝试手动只读读取,看能否读到数据
sudo dd if=/dev/vdb1 of=/dev/null bs=1M count=100 iflag=direct
解读要点(阈值为经验值):
SMART overall-health显示PASSED通常问题不大;显示FAILED基本可判定盘要坏。Reallocated_Sector_Ct(重映射扇区)持续增长,说明盘在靠备用扇区硬撑,随时可能彻底失效。Current_Pending_Sector(待定扇区)大于 0,说明有读不出来的坏道,此时首要任务是备份数据,而不是 fsck。dd读取如果卡住或报Input/output error,几乎可以确定是硬件或链路问题。
三、应急第一步:抢救数据,而不是急着重启
很多人的第一反应是"重启一下试试"。这个动作在磁盘出问题时非常危险:重启会触发 fsck/日志重放,如果盘本身有坏道,重放过程可能写入失败,把文件系统推向更严重的损坏。
正确的应急顺序是:
- 如果文件系统还能以只读方式读到数据,先尽快把重要数据复制出去。
- 复制的目标盘不能是同一块问题盘。
- 复制完再考虑修复。
# 数据还能读时,优先用 rsync 增量拷到其他磁盘或远程
sudo mkdir -p /backup/data
sudo rsync -av --progress /data/ /backup/data/
# 如果是底层块设备坏道,可考虑 ddrescue 做镜像(跳过坏块,能救多少救多少)
sudo apt install -y gddrescue # Debian/Ubuntu
sudo yum install -y ddrescue # RHEL/CentOS/Rocky
sudo ddrescue -f -n /dev/vdb1 /backup/vdb1.img /backup/vdb1.map
风险提示:
ddrescue会读写设备,命令里的源和目标写反会把数据抹掉。务必先确认源是问题盘、目标是镜像文件所在的健康盘。回滚方式:镜像文件本身是只读备份,不存在回滚问题,但要确保目标盘容量足够。
四、确认硬件没问题后,开始修复文件系统
修复前必须满足一个前提:文件系统已经卸载。挂载状态下修复会失败或造成进一步损坏。如果文件系统正在被使用,需要先停掉相关进程。
# 1. 找出占用该目录的进程
sudo lsof +D /data
sudo fuser -mv /data
# 2. 停止相关服务(示例)
sudo systemctl stop nginx mysqld
# 3. 卸载文件系统
sudo umount /data
# 如果提示 target is busy,先处理占用进程,或延迟卸载后检查
# sudo umount -l /data # 仅在确认无写入时使用
ext4 的修复
# ext4 用 e2fsck。先备份分区表以防万一
sudo sfdisk -d /dev/vdb > /root/vdb-partition.bak
# 只检查不修改(先看问题有多严重)
sudo e2fsck -fn /dev/vdb1
# 正式修复:-p 自动修复安全项,-y 全部回答 yes,-f 强制检查
sudo e2fsck -fy /dev/vdb1
e2fsck 的常见参数含义:-f 强制检查即使文件系统标记为 clean,-y 对所有询问自动回答 yes,-p 自动修复不需要人工确认的安全问题。第一次修复建议用 -p 而不是 -y,因为 -y 对一些会丢数据的询问也会自动确认,可能扩大损失。
XFS 的修复
XFS 的修复工具是 xfs_repair,逻辑与 e2fsck 不同:XFS 通常是先尝试挂载触发日志重放,避免直接 repair。
# 1. 先尝试重新挂载,XFS 会自动做日志重放(log replay),很多时候这一步就好了
sudo mount -o rw /dev/vdb1 /data
# 2. 如果挂载失败,才用 xfs_repair
sudo xfs_repair -n /dev/vdb1 # 只读检查,先看有什么问题
# 3. 正式修复(-L 会清空日志,仅在日志区损坏导致无法挂载时使用)
sudo xfs_repair /dev/vdb1
# 4. 如果提示 "log is dirty" 且 repair 拒绝执行
sudo xfs_repair -L /dev/vdb1
xfs_repair -L(清空日志)是高危操作:它会丢弃未提交的日志内容,可能造成文件丢失或目录结构异常。只有在确认日志区损坏、且没有更好的办法时才使用,使用前务必已经备份数据。
修复完成后,重新挂载并把 /etc/fstab 加上 nofail,避免修复失败时系统卡在启动:
sudo mount -a
findmnt /data
df -h /data
五、防止再次变成只读
修好之后,做下面几件事降低复发概率:
# 1. 挂载参数加 errors=remount-ro(ext4,默认行为)或明确指定
# /etc/fstab:
# /dev/vdb1 /data ext4 defaults,noatime,errors=remount-ro 0 2
# 2. 用 UPS 或云盘的写缓存策略,避免掉电导致元数据损坏
# 对数据库类业务,挂载加 noatime 并确认云盘开启 write-through 或定期快照
# 3. 定期做只读检查
sudo xfs_repair -n /dev/vdb1 # XFS
sudo e2fsck -fn /dev/vdb1 # ext4,需卸载
# 4. 监控磁盘健康(SMART + dmesg 关键字告警)
sudo smartctl -H /dev/vdb
六、几种典型场景的处理建议
- 突然掉电后变只读:绝大多数是元数据损坏,先尝试重新挂载触发日志重放,不行再 repair,成功率较高。
- SMART 已报 FAILED:优先备份数据并安排更换磁盘,不要在生产盘上反复 fsck。
- 多个文件系统同时变只读:可能不是盘的问题,而是虚拟化层/存储后端异常、或 RAID 卡电池故障导致写缓存策略变化,应检查硬件 RAID 控制器日志。
/根分区变只读:无法直接卸载,需要进入救援模式或单用户模式,用 live CD 或云主机控制台的救援系统挂载后修复。
七、修复之后怎么确认"真的好了"
修复不是敲完 e2fsck 或 xfs_repair 就结束了,还要做几件事确认文件系统恢复健康:
# 1. 重新挂载为可写
sudo mount -o rw /dev/vdb1 /data
# 2. 再次只读检查,确认没有残留错误
sudo xfs_repair -n /dev/vdb1 # XFS,需卸载后执行完整检查
sudo e2fsck -fn /dev/vdb1 # ext4,需卸载
# 3. 实际写测试
dd if=/dev/zero of=/data/.write_test bs=1M count=512 conv=fsync && rm -f /data/.write_test
# 4. 检查关键数据是否还在(尤其 lost+found 里有没有东西)
ls -la /data
sudo ls -la /data/lost+found | head
# 5. 持续观察一段时间,看 dmesg 有没有再报错
sudo dmesg -T | grep -iE "error|corrupt" | tail
sudo journalctl -k --since "1 hour ago" | grep -iE "xfs|ext4|I/O"
有一个容易被忽视的点:修复后如果 lost+found 里出现了大量文件,说明有相当一部分文件的目录归属关系已经无法恢复。这些文件虽然内容还在,但文件名丢失、路径错乱,需要人工辨认和归位。这是"元数据损坏"最典型的后果,也再次印证了"先备份再修复"的必要性——如果修复前做过完整备份,至少还有一份对照。
另外,如果同一块盘在短期内反复变成只读,即使每次 repair 都能修好,也强烈建议安排更换磁盘。反复损坏通常意味着盘体、线缆或 RAID 卡已经进入不稳定状态,靠软件修复只是拖延,下次可能是彻底的硬件失效。
常见问题
Q1:fsck 会不会把数据搞丢?
自动修复一般不会主动删数据,但在处理"目录项指向不存在节点""重复块引用"这类问题时,可能把无法确认归属的节点丢进 lost+found,或删除明显损坏的目录项。所以修复前一定要先备份。
Q2:XFS 能像 ext4 那样用 fsck 吗?
不能。XFS 没有 fsck 工具,对应的是 xfs_repair。而且 XFS 优先靠日志重放自愈,通常先尝试挂载而不是直接 repair。
Q3:修复后还是只读,怎么办?
说明根因没解决。回看 dmesg,如果还有 I/O error,就是硬件问题,硬修文件系统无意义,应更换磁盘并从备份恢复。
Q4:能不能不卸载就直接修复?
不能。ext4 的 e2fsck 在挂载状态下运行会导致数据损坏;XFS 的 xfs_repair 也要求文件系统未挂载(-n 只读模式除外)。/ 分区必须走救援模式。
Q5:只读模式会自愈吗?
不会。内核把文件系统设成只读后不会自动恢复为可写,必须人工介入。
总结
- 磁盘变只读是内核的保护动作,根因可能是文件系统损坏,也可能是硬盘/线缆/掉电。
- 第一步永远是看
dmesg/journalctl -k,用日志区分"文件系统损坏"和"硬件 I/O 错误"。 - 出现
Buffer I/O error或 SMART 异常时,优先抢救数据、更换磁盘,而不是反复修复。 - 修复的前提是卸载文件系统;ext4 用
e2fsck -fn先看再用-fy,XFS 用xfs_repair -n先看再修。 xfs_repair -L清空日志是最后手段,会丢未提交数据,用前必须备份。- 任何修复前先做磁盘镜像或数据备份,是唯一可靠的保险;原地修复没有"回滚"这一说。
企业QQ咨询




