使用Bash向分区指定位置写入随机数据块并校验的实现方法
核心问题排查
你写的两个版本脚本都存在基础逻辑错误,读回全0的常见原因按优先级排序:
- 没有root权限:块设备读写必须用root身份执行,普通用户调用dd写分区会直接静默失败,磁盘上根本没有写入任何数据,读回自然全0
- dd参数完全缺失:第二版脚本写入时没加
seek参数指定偏移,默认从分区开头写;读回时没加skip参数跳到写入位置,默认从分区开头读,完全没对应上你要的偏移位置 - 没有处理缓存:写完数据后没有刷新磁盘缓存和系统页缓存,读操作直接命中旧的缓存数据,拿到写入前的内容
- 第一版用shell变量存二进制数据:Bash的字符串变量无法正确存储包含
\0空字节的二进制内容,随机数据会被自动截断,从根源上数据就是错的
正确可运行脚本
完全对齐你之前C++实现的逻辑,脚本必须用sudo执行,运行前确认目标分区路径正确,避免写错盘丢数据:
#!/bin/bash # -------------------------- 配置项 按需修改 -------------------------- TARGET_PART="/dev/sdb1" # 替换为实际目标分区路径,再三确认不要写错盘 WRITE_OFFSET=10485760 # 分区内写入偏移,单位字节,示例为10MB位置 RAND_DATA_SIZE=10485760 # 生成随机数据总大小,单位字节,示例为10MB VERIFY_READ_SIZE=5242880 # 校验时读取大小,单位字节,示例为5MB TMP_RAND_FILE="/tmp/rand_tmp.bin" TMP_READ_FILE="/tmp/read_tmp.bin" # ------------------------------------------------------------------- # 生成10MB随机数据 head -c "$RAND_DATA_SIZE" /dev/urandom > "$TMP_RAND_FILE" # 写入数据到分区指定偏移,conv=fsync确保数据物理写入磁盘,不是停留在缓存 dd if="$TMP_RAND_FILE" of="$TARGET_PART" \ bs=4M \ seek=$((WRITE_OFFSET / 4 / 1024 / 1024)) \ conv=fsync \ status=progress # 刷新缓存,避免读回旧数据 sync echo 3 > /proc/sys/vm/drop_caches # 从指定偏移读回待校验长度的数据 dd if="$TARGET_PART" of="$TMP_READ_FILE" \ bs=4M \ skip=$((WRITE_OFFSET / 4 / 1024 / 1024)) \ count=$((VERIFY_READ_SIZE / 4 / 1024 / 1024)) \ status=progress # 二进制对比校验 if cmp -n "$VERIFY_READ_SIZE" "$TMP_RAND_FILE" "$TMP_READ_FILE"; then echo "校验通过:数据写入正确" rm -f "$TMP_RAND_FILE" "$TMP_READ_FILE" exit 0 else echo "校验失败:写入数据与原数据不匹配" rm -f "$TMP_RAND_FILE" "$TMP_READ_FILE" exit 1 fi
参数说明
- dd操作统一用4M块大小提升读写速度,偏移和长度计算时自动换算成对应块数,避免用bs=1导致的读写性能极差问题
- 写入时加
conv=fsync参数,dd返回时数据已经真正写入磁盘,不会残存在内存缓存中 - 写完手动清空页缓存,彻底避免读到旧缓存数据的问题
- 用
cmp直接做二进制比较,比字符串比较更可靠,专门适配二进制文件场景
重要提醒:磁盘分区操作有数据丢失风险,正式运行前务必在测试分区上验证逻辑,反复确认目标分区路径无误再执行。
内容的提问来源于stack exchange,提问作者Mickthekangaroo
相关产品推荐
相关产品推荐

