BTRFS 文件损坏排查与修复指南

首页 / 默认分类 / 正文
BTRFS 文件损坏排查与修复指南
运维手册

BTRFS 文件损坏排查与修复指南

基于 FNOS v1.1.26 + Proxmox VE 虚拟机环境的完整处理流程

环境: FNOS v1.1.26 / PVE 文件系统: BTRFS 存储: vol1 (800GB) + vol2 (8.79TB)

01 问题概述与日志分析

1
现象描述

FNOS 虚拟机启动后,登录界面持续输出 BTRFS 错误日志,corrupt 计数从 2450 持续增长到 2481,表明文件系统检测到了数据损坏。

2
查看详细内核日志

登录系统后,执行以下命令查看完整的 BTRFS 错误信息:

sudo dmesg | grep -i btrfs

关键错误信息示例:

BTRFS warning (device dm-0): csum failed root 5 ino 26287227 off 11952128
  csum 0x4c4c8746 expected csum 0x20a86902 mirror 1
BTRFS error (device dm-0): bdev /dev/mapper/trim_50933956_...-0
  errs: wr 0, rd 0, flush 0, corrupt 2450, gen 0
关键字段解读 csum failed 表示数据块校验和不匹配,说明存储的数据与校验记录不一致,发生了静默数据损坏(bit rot)。ino 26287227 是损坏文件的 inode 编号,off 11952128 是文件内的偏移量。
3
确认存储布局

查看系统硬盘配置:

编号容量类型用途
132 GBHDD系统安装盘
28.79 TBHDD存储空间 2 → /vol2
3100 GBSSD存储空间 2 缓存
4800 GBHDD存储空间 1 → /vol1

查看各存储空间使用情况:

df -h /vol1 /vol2

02 执行 BTRFS Scrub 检查

什么是 BTRFS Scrub? Scrub 会全量读取硬盘上的所有数据,并与校验和进行比对。如果发现不一致,会尝试从冗余副本(如有 RAID 配置)中修复;如果没有冗余,则标记为不可修复(uncorrectable)。
1
对 vol1 执行 scrub
# 启动 scrub
sudo btrfs scrub start /vol1

# 查看执行状态
sudo btrfs scrub status /vol1
2
对 vol2 执行 scrub
sudo btrfs scrub start /vol2
sudo btrfs scrub status /vol2
3
解读 scrub 结果

实际执行结果(vol1):

UUID:             163cbaa2-9373-4c8c-bde4-9a69b404f762
Scrub started:    Sat Mar 28 14:38:59 2026
Status:           finished
Duration:         0:32:25
Total to scrub:   228.24GiB
Rate:             120.17MiB/s
Error summary:    csum=1
  Corrected:      0
  Uncorrectable:  1
  Unverified:     0
结果说明 Uncorrectable: 1 表示有 1 个数据块损坏且无法自动修复。因为这是单盘配置,没有冗余副本可供恢复。

03 定位损坏文件

1
根据 inode 查找文件路径

从 dmesg 日志中获取 inode 编号(ino 26287227),然后查找对应文件:

sudo find / -inum 26287227

实际输出:

/vol1/docker/containers/960c13148dfe.../960c13148dfe...-json.log
2
确认文件性质

该文件是 Docker 容器的日志文件,属于可再生数据,非关键业务文件。

# 查看损坏文件详情
ls -lh /vol1/docker/containers/960c13148dfe.../960c13148dfe...-json.log

# 查看是哪个容器的日志
docker ps -a --filter "id=960c13148dfe"
3
全量扫描(推荐)

除 inode 定位外,建议对整个存储空间做一次完整性扫描,排查是否有其他损坏文件:

# 方法一:find 遍历并记录读取失败的文件
sudo find /vol1 -type f -exec cat {} >/dev/null 2>>/tmp/damaged_files.log \;

# 方法二:rsync 备份并记录错误(推荐,可同时完成备份)
rsync -avh --progress /vol1/ /vol2/backup/vol1/ 2>>/tmp/backup_errors.log

04 根据场景处理损坏文件

处理方式取决于损坏文件的类型和是否有备份。以下是三种典型场景:

场景 A:损坏文件是可再生数据(日志、缓存、临时文件)

判断依据:日志文件(*.log)、缓存目录(/cache/)、临时文件(/tmp/)等。

方法一:清空文件

sudo truncate -s 0 /vol1/docker/containers/960c13148dfe.../960c13148dfe...-json.log

方法二:删除并重建

# 先停止对应容器
docker stop 960c13148dfe

# 删除损坏的日志文件
sudo rm /vol1/docker/containers/960c13148dfe.../960c13148dfe...-json.log

# 重启容器,Docker 会自动重建日志文件
docker start 960c13148dfe
结论:此场景风险最低,删除或清空即可,数据可自动重建。
场景 B:损坏文件是重要数据,但有备份

判断依据:用户文档、数据库文件、照片视频等,且有定期备份。

处理步骤

# 1. 确认备份中该文件完好
ls -lh /vol2/backup/path/to/file

# 2. 从备份恢复
cp /vol2/backup/path/to/file /vol1/path/to/file

# 3. 或者直接删除损坏文件,从备份重新拷贝
sudo rm /vol1/path/to/damaged_file
cp /vol2/backup/path/to/damaged_file /vol1/path/to/
注意:恢复后务必执行一次 scrub 确认文件系统状态。
场景 C:损坏文件是重要数据,且没有备份

判断依据:关键业务数据、数据库、不可再生的文件,且无任何备份。

残酷的现实 btrfs scrub 扫出的 uncorrectable errors 就是无法修正的错误。单盘配置下没有冗余副本可供恢复。如果没有备份,数据大概率已永久丢失。

最后的尝试

# 尝试读取文件内容(可能部分数据仍可读取)
sudo cat /vol1/path/to/damaged_file > /tmp/recovered_partial 2>/dev/null

# 检查恢复了多少
ls -lh /tmp/recovered_partial

如果文件完全无法读取,只能删除后重新获取或从其他来源重建。

05 验证修复结果

1
重新执行 scrub
sudo btrfs scrub start /vol1
2
确认错误归零
sudo btrfs scrub status /vol1

期望看到:

Error summary:    csum=0
  Corrected:      0
  Uncorrectable:  0
  Unverified:     0
3
确认内核日志不再报错
dmesg | grep -i "btrfs error"

如果没有新的错误输出,说明问题已彻底解决。

06 预防措施与定时任务

核心原则:RAID ≠ 备份 硬件冗余(RAID)保护的是硬件故障,不能防止数据损坏、误删、勒索病毒等逻辑错误。重要数据一定要有独立备份。
1
设置定时 Scrub

FNOS Web 控制台中没有文件一致性校验的入口,需要手动添加 crontab:

# 一条命令添加:每月1号凌晨3点对 vol1 和 vol2 执行 scrub
(crontab -l 2>/dev/null; echo "0 3 1 * * /usr/sbin/btrfs scrub start /vol1 && /usr/sbin/btrfs scrub start /vol2") | crontab -

# 验证 crontab 是否添加成功
crontab -l
Scrub 频率建议 根据三个维度调整:硬件稳定性、硬盘健康度、数据重要性。频率范围从一周一次到六个月一次。Scrub 会全量读取硬盘,对 IO 有一定压力,建议在低峰时段执行。
2
限制 Docker 日志大小

避免日志文件过大导致类似问题:

# 编辑 Docker 配置
sudo nano /etc/docker/daemon.json

添加以下内容:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "50m",
    "max-file": "3"
  }
}
# 重启 Docker 服务
sudo systemctl restart docker
3
建立定期备份策略

建议遵循 3-2-1 备份原则:

原则说明
3 份副本重要数据至少保留 3 份
2 种介质存储在 2 种不同的介质上(如本地盘 + 外接盘)
1 份异地至少 1 份存放在异地(如云存储、另一台 NAS)

07 硬件稳定性排查

数据损坏的常见原因 静默数据损坏(bit rot)通常由以下因素引起:硬盘故障、内存错误、电源不稳定、SATA 线缆/转接板质量差、温度过高等。
排查项检查方法说明
硬盘健康 sudo smartctl -a /dev/sdX 查看 S.M.A.R.T. 状态,关注重分配扇区数、待映射扇区数
内存稳定性 MemTest86+ 或 memtester 内存错误是 BTRFS 损坏的常见原因,建议使用 ECC 内存
电源稳定性 使用 UPS / 检查电源规格 电压波动可能导致写入不完整
温度监控 sudo hddtemp /dev/sdX 硬盘温度过高会加速老化
线缆/转接板 物理检查 SATA 线缆松动或劣质转接板是常见隐患
特别注意:PVE 虚拟化环境 您的 FNOS 运行在 PVE 虚拟机中,硬盘类型为 SCSI(QEMU_HARDDISK),健康状态显示"不支持检测"。虚拟机环境下无法直接获取物理硬盘的 S.M.A.R.T. 信息,需要在 PVE 宿主机上执行 smartctl 检查。

处理流程总览

Step 1 — 发现问题

dmesg | grep -i btrfs 查看内核日志,确认 BTRFS 错误类型和 inode 编号

Step 2 — 全面检查

btrfs scrub start /vol1 && btrfs scrub start /vol2 对所有存储空间执行完整性校验

Step 3 — 定位文件

find / -inum [inode编号] 找到具体损坏文件

Step 4 — 评估影响

判断文件类型:可再生数据 → 直接删除;重要数据 → 从备份恢复;无备份 → 尝试部分恢复

Step 5 — 执行修复

根据场景选择清空、删除、恢复或重建

Step 6 — 验证结果

重新 scrub + 检查 dmesg,确认 Uncorrectable = 0

Step 7 — 长期预防

定时 scrub + 限制日志大小 + 建立备份策略 + 硬件稳定性排查

本文档基于 FNOS v1.1.26 + Proxmox VE 虚拟机环境编写

参考来源:ruohai.wang/202506/recover-file-damage

无标签
评论区
头像