BTRFS 文件损坏排查与修复指南
基于 FNOS v1.1.26 + Proxmox VE 虚拟机环境的完整处理流程
01 问题概述与日志分析
FNOS 虚拟机启动后,登录界面持续输出 BTRFS 错误日志,corrupt 计数从 2450 持续增长到 2481,表明文件系统检测到了数据损坏。
登录系统后,执行以下命令查看完整的 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 是文件内的偏移量。
查看系统硬盘配置:
| 编号 | 容量 | 类型 | 用途 |
|---|---|---|---|
| 1 | 32 GB | HDD | 系统安装盘 |
| 2 | 8.79 TB | HDD | 存储空间 2 → /vol2 |
| 3 | 100 GB | SSD | 存储空间 2 缓存 |
| 4 | 800 GB | HDD | 存储空间 1 → /vol1 |
查看各存储空间使用情况:
df -h /vol1 /vol2
02 执行 BTRFS Scrub 检查
# 启动 scrub
sudo btrfs scrub start /vol1
# 查看执行状态
sudo btrfs scrub status /vol1
sudo btrfs scrub start /vol2
sudo btrfs scrub status /vol2
实际执行结果(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 定位损坏文件
从 dmesg 日志中获取 inode 编号(ino 26287227),然后查找对应文件:
sudo find / -inum 26287227
实际输出:
/vol1/docker/containers/960c13148dfe.../960c13148dfe...-json.log
该文件是 Docker 容器的日志文件,属于可再生数据,非关键业务文件。
# 查看损坏文件详情
ls -lh /vol1/docker/containers/960c13148dfe.../960c13148dfe...-json.log
# 查看是哪个容器的日志
docker ps -a --filter "id=960c13148dfe"
除 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 根据场景处理损坏文件
处理方式取决于损坏文件的类型和是否有备份。以下是三种典型场景:
判断依据:日志文件(*.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
判断依据:用户文档、数据库文件、照片视频等,且有定期备份。
处理步骤
# 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/
判断依据:关键业务数据、数据库、不可再生的文件,且无任何备份。
最后的尝试
# 尝试读取文件内容(可能部分数据仍可读取)
sudo cat /vol1/path/to/damaged_file > /tmp/recovered_partial 2>/dev/null
# 检查恢复了多少
ls -lh /tmp/recovered_partial
如果文件完全无法读取,只能删除后重新获取或从其他来源重建。
05 验证修复结果
sudo btrfs scrub start /vol1
sudo btrfs scrub status /vol1
期望看到:
Error summary: csum=0
Corrected: 0
Uncorrectable: 0
Unverified: 0
dmesg | grep -i "btrfs error"
如果没有新的错误输出,说明问题已彻底解决。
06 预防措施与定时任务
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
避免日志文件过大导致类似问题:
# 编辑 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-2-1 备份原则:
| 原则 | 说明 |
|---|---|
| 3 份副本 | 重要数据至少保留 3 份 |
| 2 种介质 | 存储在 2 种不同的介质上(如本地盘 + 外接盘) |
| 1 份异地 | 至少 1 份存放在异地(如云存储、另一台 NAS) |
07 硬件稳定性排查
| 排查项 | 检查方法 | 说明 |
|---|---|---|
| 硬盘健康 | sudo smartctl -a /dev/sdX |
查看 S.M.A.R.T. 状态,关注重分配扇区数、待映射扇区数 |
| 内存稳定性 | MemTest86+ 或 memtester |
内存错误是 BTRFS 损坏的常见原因,建议使用 ECC 内存 |
| 电源稳定性 | 使用 UPS / 检查电源规格 | 电压波动可能导致写入不完整 |
| 温度监控 | sudo hddtemp /dev/sdX |
硬盘温度过高会加速老化 |
| 线缆/转接板 | 物理检查 | SATA 线缆松动或劣质转接板是常见隐患 |
smartctl 检查。
处理流程总览
dmesg | grep -i btrfs 查看内核日志,确认 BTRFS 错误类型和 inode 编号
btrfs scrub start /vol1 && btrfs scrub start /vol2 对所有存储空间执行完整性校验
find / -inum [inode编号] 找到具体损坏文件
判断文件类型:可再生数据 → 直接删除;重要数据 → 从备份恢复;无备份 → 尝试部分恢复
根据场景选择清空、删除、恢复或重建
重新 scrub + 检查 dmesg,确认 Uncorrectable = 0
定时 scrub + 限制日志大小 + 建立备份策略 + 硬件稳定性排查