字数 1390,阅读大约需 7 分钟
Btrfs 的日常运维核心:scrub 早发现损坏、balance 重分布、换盘 维护冗余。本篇讲清三件套的命令、频率、最佳实践。
一、scrub:自愈核心
1.1 什么是 scrub
btrfs scrub 遍历所有 extent:
scrub 过程中:
1. 读出 extent 数据
2. 计算 CRC32C
3. 与存储的 csum 对比
4. 不一致 → 修复(用副本)或标记
scrub 跑完后会自动修复不一致的 extent(前提是有冗余)。
1.2 命令
# 启动 scrub
$ btrfs scrub start /mnt
# 看状态
$ btrfs scrub status /mnt
scrub status for /mnt
scrub started at Sun Jan 15 03:00:00 2024
status: running
duration: 00:15:30
data_extents_scanned: 5000000
tree_extents_scanned: 50000
data_extents_skipped: 0
data_bytes_scanned: 20.0GiB
tree_bytes_scanned: 1.0GiB
read_errors: 0
verify_errors: 0
csum_errors: 0
super_errors: 0
malloc_errors: 0
uncorrectable_errors: 0
unverified_errors: 0
corrected_erasures: 0
...
# 取消
$ btrfs scrub cancel /mnt
# 恢复(暂停的)
$ btrfs scrub resume /mnt
1.3 scrub 频率
原因:scrub 占用 IO,会显著降低 IO 性能(30~50%)。
1.4 自动化 scrub
systemd timer:
# /etc/systemd/system/btrfs-scrub.service
[Unit]
Description=Btrfs scrub
[Service]
Type=oneshot
ExecStart=/sbin/btrfs scrub start /mnt
# /etc/systemd/system/btrfs-scrub.timer
[Unit]
Description=Monthly Btrfs scrub
[Timer]
OnCalendar=monthly
RandomizedDelaySec=4h
Persistent=true
[Install]
WantedBy=timers.target
$ systemctl enable --now btrfs-scrub.timer
cron(传统):
# /etc/cron.d/btrfs-scrub
0 4 1 * * root /sbin/btrfs scrub start /mnt
1.5 scrub 性能
scrub 性能受限于:
调整:
# ionice:低优先级
$ ionice -c 3 /sbin/btrfs scrub start /mnt
# nice:低 CPU 优先级(影响不大)
$ nice -n 19 /sbin/btrfs scrub start /mnt
二、balance:数据重平衡
2.1 何时跑 balance
2.2 命令详解
# 基本
$ btrfs balance start /mnt
# 限制使用率
$ btrfs balance start -dusage=80 /mnt
# ^^^^^^^^^^^ 只平衡使用率 > 80% 的 chunk
# 用法:50 / 80 / 90 ...
# 转 RAID
$ btrfs balance start -dconvert=raid1 /mnt
$ btrfs balance start -dconvert=raid5 /mnt
# 转 metadata
$ btrfs balance start -mconvert=raid1 /mnt
# 暂停
$ btrfs balance pause /mnt
# 恢复
$ btrfs balance resume /mnt
# 取消
$ btrfs balance cancel /mnt
# 状态
$ btrfs balance status /mnt
2.3 balance 性能
balance 写大量新 extent,IO 密集。
# 限制 IO
$ ionice -c 3 btrfs balance start /mnt
# 分批
$ for usage in 80 60 40 20; do
btrfs balance start -dusage=$usage /mnt
wait
done
2.4 多久跑一次
不需要每月跑——这是常见误区。
三、换盘
3.1 故障盘识别
# 1. 看文件系统状态
$ btrfs filesystem show /mnt
# 某盘 missing 或 error
# 2. 看设备错误
$ btrfs device stats /mnt
/dev/sdb [/mnt].write_io_errs 0
/dev/sdb [/mnt].read_io_errs 0
/dev/sdb [/mnt].flush_io_errs 0
/dev/sdb [/mnt].corruption_errs 0
# 错误数 > 0:盘可能有问题
3.2 故障处理流程
# 1. 确认盘坏了(SMART + dmesg)
$ smartctl -a /dev/sdb
$ dmesg | tail
# 2. 移除 missing 盘
$ btrfs device remove missing /mnt
# 或
$ btrfs device remove /dev/sdb /mnt
# 3. 物理换新盘
# 4. 加新盘
$ btrfs device add /dev/sdb_new /mnt
# 5. balance 重建数据
$ btrfs balance start -dusage=0 /mnt
# 6. scrub 验证
$ btrfs scrub start /mnt
3.3 在线 replace
# 一步搞定(旧盘 → 新盘)
$ btrfs replace start /dev/sdb /dev/sdb_new /mnt
# 看进度
$ btrfs replace status /mnt
# 或
$ btrfs replace status /dev/sdb
# 取消
$ btrfs replace cancel /mnt
注意:
- •
btrfs replace 在较新的内核中才有(≥ 4.18 推荐) - • 旧内核用 add + balance + remove 流程
四、scrub + balance + replace 组合实战
场景 1:定期维护
# 每月 1 号 4 点跑 scrub
$ /sbin/btrfs scrub start /mnt
# 看状态
$ btrfs scrub status /mnt
# 跑完会自动结束
场景 2:加盘扩容
# 1. 加盘
$ btrfs device add /dev/sdX /mnt
# 2. balance(让数据分布到新盘)
$ btrfs balance start -dusage=0 /mnt
# 3. 看进度
$ btrfs balance status /mnt
# 4. 完成后跑 scrub 验证
$ btrfs scrub start /mnt
场景 3:换盘
# 1. replace(一步)
$ btrfs replace start /dev/sdb /dev/sdb_new /mnt
# 2. 监控
$ btrfs replace status /mnt
# 3. 跑 scrub
$ btrfs scrub start /mnt
五、监控与告警
5.1 关键指标
| | |
|---|
data_bytes_scanned | | |
read_errors | | |
verify_errors | | |
csum_errors | | |
super_errors | | |
unverified_errors | | |
5.2 智能告警脚本
#!/bin/bash
# /usr/local/bin/btrfs-monitor.sh
MOUNT=$1
STATE=$(btrfs device stats -c $MOUNT 2>/dev/null)
# 1. 看是否有设备错误
for dev in $(ls /sys/fs/btrfs/*/devices/ 2>/dev/null); do
ERRORS=$(cat $dev/error_count 2>/dev/null)
if [ "$ERRORS" -gt 0 ]; then
echo "ALERT: device $(basename $dev) has $ERRORS errors"
# mail -s "Btrfs Error" root
fi
done
# 2. 容量检查
USED=$(btrfs filesystem usage -b $MOUNT 2>/dev/null | grep "Used:" | awk '{print $2}' | head -1)
TOTAL=$(btrfs filesystem usage -b $MOUNT 2>/dev/null | grep "Device size" | awk '{print $3}' | head -1)
PCT=$((USED * 100 / TOTAL))
if [ "$PCT" -gt 90 ]; then
echo "ALERT: $MOUNT is $PCT% full"
fi
5.3 长期监控工具
- • btrfsmaintenance(SUSE):自动 balance / scrub / trim
- • snapper(SUSE):自动快照 + 清理
- • 自定义 Prometheus exporter(自建)
六、defragment 整理碎片
# 看碎片情况
$ filefrag -v /mnt/data/bigfile | head
# 整理
$ btrfs filesystem defragment /mnt/data/bigfile
# 递归
$ btrfs filesystem defragment -r /mnt/data
# 同时压缩
$ btrfs filesystem defragment -r -czstd /mnt/data
注意:defragment 写时复制,会消耗空间。一般 不需要跑。
七、SSD trim
# 启用 mount 选项
# /etc/fstab
UUID=... /mnt btrfs subvol=@,compress=zstd,discard,defaults 0 0
# ^^^^^^^ 自动 trim
# 或手动
$ fstrim /mnt
八、本篇小结
| | |
|---|
| btrfs scrub start /mnt | |
| btrfs balance start /mnt | |
| btrfs replace start old new /mnt | |
| btrfs filesystem defragment /mnt | |
运维口诀: