badblocks 命令用于检查磁盘设备上的坏道(坏扇区)。它可以通过读写测试来识别磁盘中的不可靠扇区,并生成坏道列表,以便后续使用 e2fsck 或 mke2fs 等工具将这些扇区标记为不可用。
badblocks 的写入测试会破坏数据! 在使用 -w 选项前,请确保已备份所有重要数据,并且不要在已挂载的文件系统上运行写入测试。
badblocks [选项] 设备 [结束块 [起始块]]
badblocks [选项] -o 输出文件 设备
设备可以是磁盘设备(如 /dev/sda)或分区(如 /dev/sda1)。
| 选项 | 说明 |
|---|---|
| -v | 详细模式,显示测试的详细信息 |
| -s | 显示测试进度 |
| -o 文件 | 将坏道列表输出到指定文件 |
| -n | 非破坏性读写测试(默认模式) |
| -w | 破坏性写入测试(会破坏数据) |
| -c 数量 | 每次测试的块数(默认16) |
| -b 大小 | 块大小(字节),默认为1024 |
| -i 文件 | 从文件中读取已知的坏道列表 |
| -t 测试模式 | 指定测试模式(随机数模式) |
| -f | 强制在已挂载的设备上运行(危险!) |
| -p 次数 | 重复扫描的次数,用于确认坏道 |
| -h | 显示帮助信息 |
安全模式 - 不会破坏现有数据
适用场景:已包含数据的磁盘检查
危险模式 - 会完全破坏数据!
适用场景:全新磁盘或已备份的磁盘
# 只读检查,不修改数据
sudo badblocks -v /dev/sdb
# 检查指定分区
sudo badblocks -vs /dev/sda1
# 检查并显示进度
sudo badblocks -sv /dev/sdb
Checking blocks 0 to 2097151
Checking for bad blocks (read-only test): done
Pass completed, 0 bad blocks found.
# 非破坏性读写测试(较慢但安全)
sudo badblocks -nsv /dev/sdb
# 指定输出文件
sudo badblocks -nsv -o badblocks.txt /dev/sdb
# 增加每次测试的块数以提高速度
sudo badblocks -nsv -c 128 /dev/sdb
# 破坏性写入测试(4种模式)
sudo badblocks -wsv /dev/sdb
# 使用指定模式测试
sudo badblocks -wsv -t 0xaa /dev/sdb
# 多次重复测试以确认坏道
sudo badblocks -wsv -p 3 /dev/sdb
# 检查从0到10000的块
sudo badblocks -sv /dev/sdb 10000
# 检查从1000到10000的块
sudo badblocks -sv /dev/sdb 10000 1000
# 检查最后1000个块(需要先知道总块数)
sudo fdisk -l /dev/sdb # 查看总扇区数
# 假设总块数为N
sudo badblocks -sv /dev/sdb $((N-1)) $((N-1000))
# 从文件读取已知坏道列表
sudo badblocks -sv -i known_bad.txt /dev/sdb
# 结合检查,跳过已知坏道
sudo badblocks -nsv -i known_bad.txt -o new_bad.txt /dev/sdb
#!/bin/bash
# 磁盘健康检查脚本
DISK="/dev/sdb"
LOG_FILE="/var/log/disk_health.log"
REPORT_FILE="/var/log/disk_report_$(date +%Y%m%d).txt"
log_message() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
check_disk_info() {
echo "=== 磁盘信息 ===" | tee -a "$REPORT_FILE"
sudo fdisk -l "$DISK" | tee -a "$REPORT_FILE"
echo "" | tee -a "$REPORT_FILE"
echo "=== SMART信息 ===" | tee -a "$REPORT_FILE"
if command -v smartctl &> /dev/null; then
sudo smartctl -a "$DISK" | tee -a "$REPORT_FILE"
else
echo "smartctl未安装,跳过SMART检查" | tee -a "$REPORT_FILE"
fi
echo "" | tee -a "$REPORT_FILE"
}
run_badblocks_test() {
local test_type=$1
local output_file=$2
log_message "开始 $test_type 测试"
echo "=== $test_type 测试结果 ===" | tee -a "$REPORT_FILE"
case $test_type in
"readonly")
sudo badblocks -sv "$DISK" 2>&1 | tee -a "$REPORT_FILE"
;;
"nondestructive")
sudo badblocks -nsv "$DISK" 2>&1 | tee -a "$REPORT_FILE"
;;
*)
log_message "未知测试类型: $test_type"
return 1
;;
esac
log_message "$test_type 测试完成"
echo "" | tee -a "$REPORT_FILE"
}
main() {
log_message "开始磁盘健康检查"
# 检查磁盘是否已挂载
if mount | grep -q "^$DISK"; then
log_message "警告: $DISK 已挂载,建议卸载后再进行完整测试"
echo "磁盘已挂载,仅进行只读检查" | tee -a "$REPORT_FILE"
run_badblocks_test "readonly" "$REPORT_FILE"
else
log_message "$DISK 未挂载,进行非破坏性测试"
run_badblocks_test "nondestructive" "$REPORT_FILE"
fi
check_disk_info
log_message "磁盘健康检查完成"
echo "检查报告保存至: $REPORT_FILE"
echo "详细日志保存至: $LOG_FILE"
}
main "$@"
#!/bin/bash
# 定期磁盘监控脚本
# 配置
DISKS=("/dev/sda" "/dev/sdb" "/dev/sdc")
LOG_DIR="/var/log/disk_monitor"
DAYS_TO_KEEP=30
# 创建日志目录
mkdir -p "$LOG_DIR"
# 清理旧日志
find "$LOG_DIR" -name "*.log" -mtime +$DAYS_TO_KEEP -delete
check_disk() {
local disk=$1
local log_file="$LOG_DIR/$(basename $disk)_$(date +%Y%m%d).log"
echo "检查磁盘: $disk - $(date)" > "$log_file"
echo "==========================" >> "$log_file"
# 只读检查
echo "执行只读坏道检查..." >> "$log_file"
sudo badblocks -s "$disk" >> "$log_file" 2>&1
result=$?
if [ $result -eq 0 ]; then
echo "检查完成: 未发现坏道" >> "$log_file"
else
echo "警告: 发现坏道或检查出错" >> "$log_file"
# 发送警报
echo "磁盘 $disk 发现问题,请查看日志: $log_file" | mail -s "磁盘警报" admin@example.com
fi
# 添加磁盘信息
echo "" >> "$log_file"
echo "磁盘信息:" >> "$log_file"
sudo fdisk -l "$disk" >> "$log_file" 2>&1
echo "$(date): 检查 $disk 完成" >> "$log_file"
}
# 主程序
for disk in "${DISKS[@]}"; do
if [ -b "$disk" ]; then
echo "正在检查 $disk ..."
check_disk "$disk"
else
echo "跳过不存在的磁盘: $disk"
fi
done
echo "所有磁盘检查完成"
#!/bin/bash
# 使用badblocks和e2fsck修复文件系统
PARTITION="/dev/sdb1"
MOUNT_POINT="/mnt/data"
BADBLOCKS_FILE="/tmp/badblocks.txt"
echo "=== 文件系统坏道修复流程 ==="
# 1. 卸载分区(如果已挂载)
echo "1. 卸载分区..."
if mount | grep -q "$PARTITION"; then
sudo umount "$PARTITION"
echo " 分区已卸载"
else
echo " 分区未挂载"
fi
# 2. 运行坏道检查
echo -e "\n2. 运行坏道检查..."
sudo badblocks -nsv -o "$BADBLOCKS_FILE" "$PARTITION"
# 3. 检查是否有坏道
if [ -s "$BADBLOCKS_FILE" ]; then
echo " 发现坏道,数量: $(wc -l < "$BADBLOCKS_FILE")"
# 4. 使用e2fsck标记坏道
echo -e "\n3. 标记坏道..."
sudo e2fsck -l "$BADBLOCKS_FILE" "$PARTITION"
# 5. 强制检查文件系统
echo -e "\n4. 强制检查文件系统..."
sudo e2fsck -f -v "$PARTITION"
else
echo " 未发现坏道"
fi
# 6. 重新挂载
echo -e "\n5. 重新挂载..."
sudo mount "$PARTITION" "$MOUNT_POINT"
echo -e "\n修复流程完成"
if [ -f "$BADBLOCKS_FILE" ]; then
echo "坏道列表保存于: $BADBLOCKS_FILE"
fi
将badblocks的输出提供给e2fsck,在文件系统中标记坏道:
# 生成坏道列表
sudo badblocks -o badblocks.txt /dev/sdb1
# 使用e2fsck标记坏道
sudo e2fsck -l badblocks.txt /dev/sdb1
创建文件系统时直接排除已知坏道:
# 先检查坏道
sudo badblocks -o badblocks.txt /dev/sdb
# 创建文件系统时排除坏道
sudo mke2fs -l badblocks.txt /dev/sdb1
-w 选项会永久删除磁盘上的所有数据优化建议:
sudo badblocks -c 1024 /dev/sdb
-v 而不加 -n 或 -w)中断方法:
# 找到进程ID
jobs -l
# 或使用ps查找
ps aux | grep badblocks
# 终止进程
kill -9 进程ID
处理步骤:
sudo badblocks -sv -i badblocks.txt /dev/sdb
# 对于ext2/3/4文件系统
sudo e2fsck -l badblocks.txt /dev/sdb1