强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Bcachefs 完全指南 / 第 11 章:数据恢复与故障处理

第 11 章:数据恢复与故障处理

防患于未然,亡羊补牢亦未晚


11.1 故障分类

11.1.1 故障类型矩阵

故障类型严重程度恢复难度数据丢失风险
软性损坏⭐⭐较易
Journal 损坏⭐⭐⭐中等
B-Tree 损坏⭐⭐⭐⭐较难中高
设备故障 (有副本)⭐⭐较易
设备故障 (无副本)⭐⭐⭐⭐⭐极难
全设备丢失⭐⭐⭐⭐⭐不可恢复全部

11.1.2 常见故障原因

故障原因分类:

1. 硬件故障
   ├── 磁盘坏扇区
   ├── 控制器故障
   ├── 电源故障(写入中断)
   └── 内存错误(数据损坏)

2. 软件故障
   ├── 内核 bug
   ├── 文件系统 bug
   ├── 不当操作(强制关机)
   └── 驱动程序问题

3. 人为因素
   ├── 误删除
   ├── 误格式化
   ├── 配置错误
   └── 权限问题

11.2 fsck 工具详解

11.2.1 fsck 基本用法

# 基本检查(只读模式)
sudo bcachefs fsck /dev/sdb

# 自动修复
sudo bcachefs fsck --fix-errors /dev/sdb

# 详细输出
sudo bcachefs fsck --verbose /dev/sdb

# 非常详细的输出
sudo bcachefs fsck --very-verbose /dev/sdb

# 干运行(不实际修改)
sudo bcachefs fsck --dry-run /dev/sdb

11.2.2 fsck 选项详解

选项说明
--fix-errors自动修复发现的错误
--dry-run只报告不修改
--verbose显示详细检查过程
--very-verbose显示非常详细的输出
--force强制检查(即使文件系统标记为干净)
--reconstruct-alloc重建分配信息(严重损坏时使用)
--ratelimit-errors限制错误输出速率
--check-btree只检查 B-Tree 完整性
--check-refs只检查引用计数
--check-checksums只检查校验和

11.2.3 fsck 检查流程

bcachefs fsck 检查步骤:

1. 验证超级块
   └─ 检查 magic number, 版本, UUID

2. 检查 Journal
   └─ 验证日志条目完整性
   └─ 回放未完成的事务

3. 检查 B-Tree
   └─ 验证节点完整性
   └─ 检查 key 顺序
   └─ 验证节点间链接

4. 检查引用计数
   └─ 验证数据块引用计数
   └─ 检查 inode 链接计数

5. 检查校验和
   └─ 验证数据块校验和
   └─ 标记损坏的数据块

6. 检查分配器
   └─ 验证 Bucket 分配状态
   └─ 重建分配信息(如果需要)

11.2.4 运行 fsck 的时机

# 1. 崩溃恢复后(自动检查)
# 内核会在挂载时自动运行一致性检查
dmesg | grep bcachefs

# 2. 定期预防性检查
# 建议每月检查一次
sudo bcachefs fsck --dry-run /dev/sdb

# 3. 发现异常时
# 文件消失、权限错误、空间不一致等

# 4. 内核报告错误后
dmesg | grep -i "bcachefs\|error\|corrupt"

11.3 常见故障处理

11.3.1 软性损坏(元数据不一致)

# 症状:
# - 文件操作偶尔失败
# - df 显示的空间与实际不符
# - 内核日志中有警告

# 诊断
dmesg | grep bcachefs | grep -i "warn\|error"

# 修复
sudo umount /mnt/data
sudo bcachefs fsck --fix-errors /dev/sdb

# 如果修复成功,重新挂载
sudo mount -t bcachefs /dev/sdb /mnt/data

11.3.2 Journal 损坏

# 症状:
# - 文件系统无法挂载
# - 错误信息包含 "journal"

# 诊断
sudo bcachefs show-super /dev/sdb

# 修复方案 1: 尝试 fsck
sudo bcachefs fsck --fix-errors /dev/sdb

# 修复方案 2: 跳过 Journal 回放(数据可能丢失)
sudo mount -t bcachefs -o norecovery /dev/sdb /mnt/data

# 修复方案 3: 重建 Journal
sudo bcachefs fsck --reconstruct-alloc /dev/sdb

11.3.3 B-Tree 损坏

# 症状:
# - 文件系统挂载后大量错误
# - 文件内容损坏
# - 内核报告 B-Tree 错误

# 诊断
sudo bcachefs fsck --check-btree /dev/sdb

# 修复
sudo bcachefs fsck --fix-errors /dev/sdb

# 如果自动修复失败,可能需要手动干预
# 此时考虑从备份恢复

11.3.4 设备故障(有副本)

# 症状:
# - 设备消失
# - 文件系统降级运行
# - dmesg 显示设备失败

# 诊断
dmesg | grep bcachefs
sudo bcachefs device list /mnt/data

# 处理步骤
# 1. 文件系统仍可正常使用(降级状态)
# 2. 添加新设备
sudo bcachefs device add /mnt/data /dev/sdd

# 3. 标记旧设备为故障
sudo bcachefs device set-state /mnt/data /dev/sdb failed

# 4. 移除旧设备
sudo bcachefs device remove /mnt/data /dev/sdb

# 5. 数据会自动重建到新设备

11.3.5 设备故障(无副本)

# 症状:
# - 文件系统不可用
# - 无法挂载

# 诊断
sudo bcachefs show-super /dev/sdb

# 尝试方案:
# 1. 只读模式挂载
sudo mount -t bcachefs -o ro,degraded /dev/sdb /mnt/data

# 2. 如果只读挂载成功,立即复制数据
rsync -av /mnt/data/ /mnt/recovery/

# 3. 如果无法挂载,尝试 fsck
sudo bcachefs fsck --reconstruct-alloc /dev/sdb

# 4. 如果 fsck 失败,考虑专业数据恢复服务

11.4 设备替换

11.4.1 在线设备替换

#!/bin/bash
# replace-device.sh

set -e

MOUNT="/mnt/data"
OLD_DEVICE="/dev/sdb"
NEW_DEVICE="/dev/sdc"
LABEL="data.1"

echo "=== 在线设备替换 ==="
echo "旧设备: $OLD_DEVICE"
echo "新设备: $NEW_DEVICE"

# 1. 添加新设备
echo "添加新设备..."
sudo bcachefs device add --label="$LABEL" "$MOUNT" "$NEW_DEVICE"

# 2. 迁移数据
echo "迁移数据..."
sudo bcachefs data migrate "$MOUNT" "$OLD_DEVICE"

# 3. 等待迁移完成
echo "等待迁移完成..."
while true; do
    # 检查是否还有数据在旧设备上
    USAGE=$(sudo bcachefs device show "$MOUNT" "$OLD_DEVICE" 2>/dev/null | grep -i "used" || echo "")
    if [ -z "$USAGE" ] || echo "$USAGE" | grep -q "0"; then
        echo "迁移完成"
        break
    fi
    echo "迁移中... ($USAGE)"
    sleep 10
done

# 4. 标记旧设备为故障
echo "标记旧设备为故障..."
sudo bcachefs device set-state "$MOUNT" "$OLD_DEVICE" failed

# 5. 移除旧设备
echo "移除旧设备..."
sudo bcachefs device remove "$MOUNT" "$OLD_DEVICE"

# 6. 验证
echo "验证..."
sudo bcachefs device list "$MOUNT"

echo "=== 替换完成 ==="

11.4.2 离线设备替换

# 如果设备完全故障,使用离线替换

# 1. 卸载文件系统
sudo umount /mnt/data

# 2. 尝试 fsck
sudo bcachefs fsck --fix-errors /dev/sdb

# 3. 如果 fsck 成功,重新挂载
sudo mount -t bcachefs /dev/sdb /dev/sdc /mnt/data

# 4. 如果 fsck 失败,使用 degraded 模式
sudo mount -t bcachefs -o degraded /dev/sdb /dev/sdc /mnt/data

11.5 数据恢复工具

11.5.1 使用 debugfs 手动恢复

# Bcachefs 提供调试工具(开发者用)

# 查看 B-Tree 结构
sudo bcachefs dump /dev/sdb

# 导出特定文件
# (这需要对 Bcachefs 内部结构有深入了解)

11.5.2 块级数据恢复

# 如果文件系统元数据完全损坏,但数据块仍可读
# 可以尝试块级恢复

# 使用 testdisk
sudo apt install testdisk
sudo testdisk /dev/sdb

# 使用 photorec(恢复特定文件类型)
sudo photorec /dev/sdb

# 注意: 这些工具不理解 Bcachefs 格式
# 只能通过文件签名恢复(如 JPEG 头)

11.5.3 专业数据恢复服务

当所有自助恢复手段失败时:

1. 停止使用该设备(避免覆盖数据)
2. 创建设备镜像
   dd if=/dev/sdb of=/mnt/backup/sdb.img bs=4M status=progress
3. 联系专业数据恢复公司
4. 提供设备镜像供分析

国内数据恢复服务:
- 飞客数据恢复
- DriveSavers (国际)
- Ontrack (国际)

11.6 崩溃一致性

11.6.1 Bcachefs 的崩溃保护

Bcachefs 崩溃保护机制:

1. CoW (Copy-on-Write)
   - 数据写入新位置
   - 原子更新指针
   - 崩溃后旧数据完整

2. Journal (日志)
   - 前写日志
   - 崩溃后回放日志
   - 保证事务原子性

3. 校验和
   - 检测静默数据损坏
   - 多副本自动修复

11.6.2 崩溃后恢复流程

# 崩溃后的自动恢复:
# 1. 内核自动检测 Journal
# 2. 回放未完成的事务
# 3. 文件系统恢复一致性
# 4. 挂载成功

# 如果自动恢复失败:
dmesg | grep bcachefs
# 查看具体错误信息

# 手动修复
sudo bcachefs fsck --fix-errors /dev/sdb

11.6.3 强制关机后的处理

# 强制关机可能导致:
# - Journal 中有未回放的事务
# - 脏数据丢失

# 检查文件系统
sudo bcachefs fsck --dry-run /dev/sdb

# 如果有错误,自动修复
sudo bcachefs fsck --fix-errors /dev/sdb

11.7 预防措施

11.7.1 定期备份策略

推荐备份策略:

3-2-1 原则:
  3 份数据副本
  2 种不同介质
  1 份异地存储

实施:
  ┌─────────────────────────────────────────┐
  │ 1. 本地快照(每日)                      │
  │    - Bcachefs 子卷快照                   │
  │    - 保留 7 天                           │
  ├─────────────────────────────────────────┤
  │ 2. 本地备份(每周)                      │
  │    - rsync 到另一设备                    │
  │    - 保留 4 周                           │
  ├─────────────────────────────────────────┤
  │ 3. 远程备份(每月)                      │
  │    - rsync 到远程服务器                  │
  │    - 或使用 restic/borgbackup           │
  │    - 保留 12 个月                        │
  └─────────────────────────────────────────┘

11.7.2 监控与告警

#!/bin/bash
# monitor-bcachefs-health.sh

MOUNT="/mnt/data"
ALERT_EMAIL="admin@example.com"

# 检查挂载状态
if ! mountpoint -q "$MOUNT"; then
    echo "CRITICAL: $MOUNT 未挂载" | mail -s "Bcachefs 告警" "$ALERT_EMAIL"
    exit 1
fi

# 检查内核错误
ERRORS=$(dmesg | grep -c "bcachefs.*error\|bcachefs.*corrupt")
if [ "$ERRORS" -gt 0 ]; then
    echo "WARNING: 发现 $ERRORS 个 Bcachefs 错误" | mail -s "Bcachefs 告警" "$ALERT_EMAIL"
fi

# 检查空间使用
USAGE=$(df --output=pcent "$MOUNT" | tail -1 | tr -d ' %')
if [ "$USAGE" -gt 90 ]; then
    echo "WARNING: $MOUNT 空间使用率 ${USAGE}%" | mail -s "Bcachefs 告警" "$ALERT_EMAIL"
fi

# 检查降级状态
DEVICES=$(sudo bcachefs device list "$MOUNT" 2>/dev/null | grep -c "failed\|offline")
if [ "$DEVICES" -gt 0 ]; then
    echo "CRITICAL: 发现 $DEVICES 个故障设备" | mail -s "Bcachefs 告警" "$ALERT_EMAIL"
fi

11.7.3 UPS 保护

# UPS (不间断电源) 可以防止意外断电

# 安装 apcupsd
sudo apt install apcupsd

# 配置低电量关机
# /etc/apcupsd/apcupsd.conf
# BATTERYLEVEL 15
# MINUTES 5
# TIMEOUT 0

# 关机前卸载 Bcachefs 文件系统
# /etc/apcupsd/doshutdown
umount /mnt/data

11.8 高级恢复技术

11.8.1 手动修复 B-Tree

# 仅限专家用户
# 错误操作可能导致数据完全丢失

# 查看 B-Tree 结构
sudo bcachefs dump --btree /dev/sdb

# 导出未损坏的 B-Tree 节点
sudo bcachefs dump --btree --output=/tmp/btree-dump.txt /dev/sdb

# 分析 B-Tree 完整性
# (需要对 Bcachefs 内部结构有深入了解)

11.8.2 从镜像恢复

# 创建设备镜像(保护原始数据)
sudo dd if=/dev/sdb of=/mnt/backup/sdb.img bs=4M status=progress

# 在镜像上运行 fsck
sudo bcachefs fsck /mnt/backup/sdb.img

# 如果成功,从镜像恢复
sudo mount -t bcachefs /mnt/backup/sdb.img /mnt/recovery

11.8.3 使用 bcachefs dump 导出数据

# 导出文件系统元数据
sudo bcachefs dump /dev/sdb > /tmp/bcachefs-dump.txt

# 导出特定文件的数据
# (需要编写脚本解析 dump 输出)

11.9 故障排除检查清单

#!/bin/bash
# bcachefs-troubleshoot.sh

set -e

echo "=== Bcachefs 故障排除检查清单 ==="
echo ""

DEVICE="${1:-/dev/sdb}"
MOUNT="${2:-/mnt/data}"

# 1. 设备检查
echo "1. 设备检查"
echo "   设备: $DEVICE"
if [ -b "$DEVICE" ]; then
    echo "   ✅ 设备存在"
else
    echo "   ❌ 设备不存在"
    exit 1
fi

# 2. 超级块检查
echo ""
echo "2. 超级块检查"
if sudo bcachefs show-super "$DEVICE" &>/dev/null; then
    echo "   ✅ 超级块有效"
    UUID=$(sudo bcachefs show-super "$DEVICE" | grep UUID | awk '{print $2}')
    echo "   UUID: $UUID"
else
    echo "   ❌ 超级块损坏"
fi

# 3. 模块检查
echo ""
echo "3. 模块检查"
if modinfo bcachefs &>/dev/null; then
    echo "   ✅ bcachefs 模块可用"
else
    echo "   ❌ bcachefs 模块不可用"
fi

# 4. 挂载检查
echo ""
echo "4. 挂载检查"
if mountpoint -q "$MOUNT" 2>/dev/null; then
    echo "   ✅ 已挂载到 $MOUNT"
else
    echo "   ⚠️  未挂载"
fi

# 5. 内核日志检查
echo ""
echo "5. 内核日志检查"
ERRORS=$(dmesg | grep -c "bcachefs.*error\|bcachefs.*corrupt" || echo 0)
if [ "$ERRORS" -eq 0 ]; then
    echo "   ✅ 无错误日志"
else
    echo "   ⚠️  发现 $ERRORS 个错误"
    dmesg | grep "bcachefs.*error\|bcachefs.*corrupt" | tail -5
fi

# 6. 空间检查
echo ""
echo "6. 空间检查"
if mountpoint -q "$MOUNT" 2>/dev/null; then
    USAGE=$(df --output=pcent "$MOUNT" | tail -1 | tr -d ' %')
    echo "   使用率: ${USAGE}%"
    if [ "$USAGE" -gt 90 ]; then
        echo "   ⚠️  空间不足"
    else
        echo "   ✅ 空间充足"
    fi
fi

# 7. 设备状态
echo ""
echo "7. 设备状态"
if mountpoint -q "$MOUNT" 2>/dev/null; then
    sudo bcachefs device list "$MOUNT" 2>/dev/null || echo "   无法获取设备列表"
fi

echo ""
echo "=== 检查完成 ==="

11.10 灾难恢复计划

11.10.1 灾难恢复流程

灾难恢复步骤:

1. 评估损失
   ├── 确认故障类型
   ├── 确认数据丢失范围
   └── 确认是否有备份

2. 保护现场
   ├── 停止使用故障设备
   ├── 创建设备镜像
   └── 记录故障现象

3. 恢复尝试
   ├── 从快照恢复
   ├── 从备份恢复
   ├── 使用 fsck 修复
   └── 专业数据恢复

4. 验证恢复
   ├── 检查数据完整性
   ├── 验证业务功能
   └── 记录恢复过程

5. 事后复盘
   ├── 分析故障原因
   ├── 改进预防措施
   └── 更新恢复文档

11.10.2 恢复时间目标 (RTO)

场景目标 RTO恢复方法
软性损坏< 10 分钟fsck 自动修复
设备替换< 30 分钟在线设备替换
数据恢复< 2 小时从备份恢复
全系统重建< 8 小时完整重建

11.10.3 恢复点目标 (RPO)

备份策略RPO数据丢失
每日快照24 小时最多 1 天
每 6 小时快照6 小时最多 6 小时
实时复制接近 0几乎无

11.11 本章小结

故障类型处理方法预防措施
软性损坏fsck –fix-errors定期 fsck
Journal 损坏fsck 或 norecoveryUPS 保护
B-Tree 损坏fsck 或备份恢复多副本
设备故障设备替换RAID + 备份

关键建议:

  1. 定期备份,遵循 3-2-1 原则
  2. 使用 UPS 防止意外断电
  3. 监控文件系统健康状态
  4. 保持 bcachefs-tools 更新
  5. 测试恢复流程

扩展阅读


上一章: ← 第 10 章:Docker 与容器化 | 下一章: 第 12 章:生产最佳实践 →