我有 2 个旧的 160GB WD 硬盘,使用 hdparm 查询时没有“安全删除”选项。
我了解当前人们接受用零覆盖整个磁盘的机制。
但这让我感到失望。
拥有一个像 /dev/one 这样的机制来创建一个流不是更好吗?
使轨道磁化达到最大程度难道不是比试图消除磁化更好吗?或者这就像试图达到 6-sigma 水平,而当前技术只能测量 3/4-sigma?
为此,我该如何制定命令来生成“全位开启”流来填充 512 字节宽的块?
答案1
感谢 Halfgaar 指导我了解 badblocks。这是我实现目标的理想途径。
就我家里的桌面环境而言,通过这种方式完成这项任务大约需要 54 多个小时,不间断。
我在这里附上了我为满足我的需求而编写的脚本。脚本中还包含关于原因的解释。
#!/bin/sh
BASE=`basename "$0" ".sh" `
TRACKER=./${BASE}.last
SLICE=`expr 4096 \* 16 `
echo "\n\t This utility will overwrite the full disk with all data bits ON\n\t using '0xFFFF' as test pattern for destructive badblocks scan ..."
echo "\n\t This utility will begin at the last sector and work its way towards the first sector\n\t on the disk, doing slices of ${SLICE} sectors at one time ..."
echo "\n\t The design concept is based on fact that some older USB-attached devices\n\t have both slow interface and slow disk I/O, as well as taking into account\n\t the End-User context of a Desktop computer which cannot remain up and running\n\t for 2-3 days non-stop. The process can be interrupted at any time and\n\t the script will be able to restart at the last known completed segment\n\t to continue from there."
if [ "$1" != "--force" ]
then
echo "\n\n\t As a security precaution, you MUST review the script to ensure proper\n\t understanding of DANGERS AND RISKS before proceeding.\n Bye!\n" ; exit 1
fi
echo "\n\t Enter disk (block) device path (i.e. /dev/sdb) => \c" ; read DISK
if [ -z "${DISK}" ] ; then echo "\n\t No path entered for a block device. Cannot proceed.\n Bye!\n" ; exit 1 ; fi
if [ ! -b "${DISK}" ] ; then echo "\n\t '${DISK}' is not an existing block device file. Cannot proceed.\n Bye!\n" ; exit 1 ; fi
testor=`df | grep ${DISK} | head -1 `
if [ -n "${testor}" ] ; then echo "\n\t Mounted partitions for that device:" ; echo "${testor}" | awk '{ printf("\t\t %s\n", $0 ) ; }' ; echo " Bye!\n" ; exit 1 ; fi
### Disk /dev/sdd: 149.5 GiB, 160041885696 bytes, 312581808 sectors
SECTORS_LGCL=`fdisk -l ${DISK} | grep '^Disk '${DISK} | awk '{ print $7 }' `
echo "${SECTORS_LGCL}" | awk '{ printf("\t SECTORS_LOGICAL = %12s\n", $0 ) ; }'
### Sector size (logical/physical): 512 bytes / 4096 bytes
SECT_SIZE_LGCL=`fdisk -l ${DISK} | grep '^Sector size' | awk '{ print $4 }' `
SECT_SIZE_PSCL=`fdisk -l ${DISK} | grep '^Sector size' | awk '{ print $7 }' `
CLUMPING=`expr ${SECT_SIZE_PSCL} / ${SECT_SIZE_LGCL} `
SECTORS_PSCL=`expr ${SECTORS_LGCL} / ${CLUMPING} `
echo "${SECTORS_PSCL}" | awk '{ printf("\t SECTORS_PHYSICAL = %12s\n", $0 ) ; }'
LAST_TODO=0
LAST=`expr ${SECTORS_PSCL} - 1 `
ITERATION=`expr ${LAST} - ${SLICE} + 1 `
COUNT=`expr ${SECTORS_PSCL} / ${SLICE} `
if [ -s ${TRACKER} ]
then
read ITERATION <${TRACKER}
ITERATION=`expr ${ITERATION} - ${SLICE} `
echo "\t Using last known good ITERATION captured before last abandon ..."
COUNT=`expr ${ITERATION} - 1 ` ; COUNT=`expr ${COUNT} / ${SLICE} `
fi
echo "\t Iteration countdown from $COUNT ..."
while [ ${ITERATION} -ge ${LAST_TODO} ]
do
echo "${COUNT} ${ITERATION} ${SECTORS_PSCL}" | awk '{ printf("\n\n[%s] Slice 1st sector = %12s / %s ...\n", $1, $2, $3 ) ; }'
ITERATION_LAST=`expr ${ITERATION} + ${SLICE} - 1 `
if [ ${ITERATION_LAST} -gt ${SECTORS_PSCL} ]
then
ITERATION_LAST=`expr ${SECTORS_PSCL} - 1 `
ITERATION=`expr ${ITERATION_LAST} - ${SLICE} `
fi
echo "${ITERATION_LAST}" | awk '{ printf("\tITERATION_LAST = %12s\n", $0 ) ; }'
echo "${SLICE}" | awk '{ printf("\tSLICE = %12s\n", $0 ) ; }'
echo "${ITERATION}" | awk '{ printf("\tITERATION = %12s\n", $0 ) ; }'
badblocks -v -s -w -b ${SECT_SIZE_PSCL} -p 0 -e 0 -t 0xFFFF /dev/sdd ${ITERATION_LAST} ${ITERATION}
echo "${ITERATION}" >${TRACKER}
if [ ${ITERATION} -eq ${LAST_TODO} ]
then
break
else
ITERATION=`expr ${ITERATION} - ${SLICE} `
if [ ${ITERATION} -lt ${LAST_TODO} ]
then
ITERATION=${LAST_TODO}
fi
fi
COUNT=`expr ${COUNT} - 1 `
done
exit
会话输出(重新启动后)如下所示:
This utility will overwrite the full disk with all data bits ON
using '0xFFFF' as test pattern for destructive badblocks scan ...
This utility will begin at the last sector and work its way towards the first sector
on the disk, doing slices of 65536 sectors at one time ...
The design concept is based on fact that some older USB-attached devices
have both slow interface and slow disk I/O, as well as taking into account
the End-User context of a Desktop computer which cannot remain up and running
for 2-3 days non-stop. The process can be interrupted at any time and
the script will be able to restart at the last known completed segment
to continue from there.
Enter disk (block) device path (i.e. /dev/sdb) => /dev/sdd
SECTORS_LOGICAL = 312581808
SECTORS_PHYSICAL = 312581808
Using last known good ITERATION captured before last abandon ...
Iteration countdown from 4712 ...
[4712] Slice 1st sector = 308846247 / 312581808 ...
ITERATION_LAST = 308911782
SLICE = 65536
ITERATION = 308846247
Checking for bad blocks in read-write mode
From block 308846247 to 308911782
Testing with pattern 0xffff: done
Reading and comparing: done
Pass completed, 0 bad blocks found. (0/0/0 errors)
[4711] Slice 1st sector = 308780711 / 312581808 ...
ITERATION_LAST = 308846246
SLICE = 65536
ITERATION = 308780711
Checking for bad blocks in read-write mode
From block 308780711 to 308846246
Testing with pattern 0xffff: done
Reading and comparing: done
Pass completed, 0 bad blocks found. (0/0/0 errors)
***
答案2
我想到了一个更直接的方法,使用基本的 dd 命令,希望这能加快这个过程。不幸的是,两者的计时结果几乎相同,都在 54 小时以上。
以下是“dd”方法的脚本:
#!/bin/sh
BASE=`basename "$0" ".sh" `
SEEDlocn="/site/DB003_F1"
TMP="${SEEDlocn}/${BASE}.bitsON"
ROOTlocn=`df / | grep '/dev/sd' | awk '{ print $1 }' `
testor=`df ${SEEDlocn} | grep '/dev/sd' | awk '{ print $1 }' `
if [ "${testor}" = "${ROOTlocn}" ] ; then echo "\n\t Disk for ${SEEDlocn} is not mounted. Unable to proceed.\n Bye!\n" ; exit 1 ; fi
echo "\n\t Following block devices have been identified:\n"
lsblk -l | awk '{ if( length($1) == 3 ){ print $0 } ; }' | awk '{ printf("\t\t %s\n", $0 ) ; }'
echo "\n\t Enter the block device's full path => \c" ; read DISK
if [ -z "${DISK}" ] ; then echo "\n\t Empty string.\n Bye!\n" ; exit 1 ; fi
echo "\n\t Enter the LABEL for the block device => \c" ; read LABEL
if [ -z "${LABEL}" ] ; then echo "\n\t Empty string. Need proper LABEL for unique tracking and safe/correct restart.\n Bye!\n" ; exit 1 ; fi
TRACKER="./${BASE}.${LABEL}.last"
testor=`df | grep ${DISK} `
if [ -n "${testor}" ] ; then echo "\n\t Drive is mounted on ${DISK} ... Cannot proceed.\n Bye!\n" ; exit 1 ; fi
testor=`stat ${TMP}.binaryBLOB | grep '^ Size:' | awk '{ print $2 }' `
if [ -z "${testor}" ] ; then testor="0" ; fi
if [ ${testor} -eq 1073741824 ]
then
echo "\n\t Using existing seed file '${TMP}.binaryBLOB' ..."
else
echo "\n\t Creating input to create 512 byte seed file with all bits ON ..."
### Seed file size = 512 * 8 = 4096 bytes
cat <<-EOF_EOF >${TMP}.seed
00000000: ffff ffff ffff ffff ffff ffff ffff ffff ################
00000010: ffff ffff ffff ffff ffff ffff ffff ffff ################
00000020: ffff ffff ffff ffff ffff ffff ffff ffff ################
00000030: ffff ffff ffff ffff ffff ffff ffff ffff ################
00000040: ffff ffff ffff ffff ffff ffff ffff ffff ################
00000050: ffff ffff ffff ffff ffff ffff ffff ffff ################
00000060: ffff ffff ffff ffff ffff ffff ffff ffff ################
00000070: ffff ffff ffff ffff ffff ffff ffff ffff ################
00000080: ffff ffff ffff ffff ffff ffff ffff ffff ################
00000090: ffff ffff ffff ffff ffff ffff ffff ffff ################
000000a0: ffff ffff ffff ffff ffff ffff ffff ffff ################
000000b0: ffff ffff ffff ffff ffff ffff ffff ffff ################
000000c0: ffff ffff ffff ffff ffff ffff ffff ffff ################
000000d0: ffff ffff ffff ffff ffff ffff ffff ffff ################
000000e0: ffff ffff ffff ffff ffff ffff ffff ffff ################
000000f0: ffff ffff ffff ffff ffff ffff ffff ffff ################
00000100: ffff ffff ffff ffff ffff ffff ffff ffff ################
00000110: ffff ffff ffff ffff ffff ffff ffff ffff ################
00000120: ffff ffff ffff ffff ffff ffff ffff ffff ################
00000130: ffff ffff ffff ffff ffff ffff ffff ffff ################
00000140: ffff ffff ffff ffff ffff ffff ffff ffff ################
00000150: ffff ffff ffff ffff ffff ffff ffff ffff ################
00000160: ffff ffff ffff ffff ffff ffff ffff ffff ################
00000170: ffff ffff ffff ffff ffff ffff ffff ffff ################
00000180: ffff ffff ffff ffff ffff ffff ffff ffff ################
00000190: ffff ffff ffff ffff ffff ffff ffff ffff ################
000001a0: ffff ffff ffff ffff ffff ffff ffff ffff ################
000001b0: ffff ffff ffff ffff ffff ffff ffff ffff ################
000001c0: ffff ffff ffff ffff ffff ffff ffff ffff ################
000001d0: ffff ffff ffff ffff ffff ffff ffff ffff ################
000001e0: ffff ffff ffff ffff ffff ffff ffff ffff ################
000001f0: ffff ffff ffff ffff ffff ffff ffff ffff ################
EOF_EOF
cat ${TMP}.seed
ls -l ${TMP}.seed
echo "\n\t Creating 512 byte seed file with all bits ON ..."
xxd -revert ${TMP}.seed >${TMP}.seedbinary
hexdump ${TMP}.seedbinary
ls -l ${TMP}.seedbinary
echo "\n\t Creating 2 Mbyte seed file ..."
i=4096 ### iterations will create 2 Mbyte file
while [ true ]
do
if [ ${i} -eq 0 ]
then
break
fi
cat ${TMP}.seedbinary
echo ".\c" >&2
i=`expr ${i} - 1 `
done >${TMP}.seedbinary2
echo ""
hexdump -n 512 ${TMP}.seedbinary2
ls -l ${TMP}.seedbinary2
echo "\n\t Creating 1 Gbyte seed file ..."
i=512 ### iterations will create 1 Gbyte file
while [ true ]
do
if [ ${i} -eq 0 ]
then
break
fi
cat ${TMP}.seedbinary2
echo ".\c" >&2
i=`expr ${i} - 1 `
done >${TMP}.binaryBLOB
echo ""
hexdump -n 512 ${TMP}.binaryBLOB
### 2097152 bytes
fi
ls -l ${TMP}.binaryBLOB
BS="1048576" ### 512 * 2048 bytes = 1 MByte
BLOB_SIZE="1073741824" ### 1 GBytes
SLICE_BLOCKS=`expr ${BLOB_SIZE} / ${BS} ` ### count of ${BS}-byte blocks for 1 GB file
MAX="160"
if [ -s ${TRACKER} ]
then
read SLICE <${TRACKER}
echo "\n\t TRACKER file indicates last completed slice was # ${SLICE}. Continuing with the next slice ..."
SLICE=`expr ${SLICE} + 1 `
else
SLICE=1
fi
REMAIN=`expr ${MAX} - ${SLICE} `
while [ true ]
do
START_BLOCK=`expr ${SLICE} - 1 `
START_BLOCK=`expr ${START_BLOCK} \* ${SLICE_BLOCKS} `
echo "\n\t [${REMAIN}] Doing slice ${SLICE} of ${MAX} ..."
COM="dd status=progress bs=${BS} if=${TMP}.binaryBLOB count=${SLICE_BLOCKS} seek=${START_BLOCK} of=${DISK} iflag=fullblock conv=notrunc,fdatasync oflag=dsync"
echo "\t ${COM} ..."
${COM}
RC=$?
date
if [ ${RC} -ne 0 ] ; then echo "\n\t ERROR encounted. RC = ${RC} ...\n Bye!\n" ; exit 1 ; fi
echo "${SLICE}" >${TRACKER}
SLICE=`expr ${SLICE} + 1 `
REMAIN=`expr ${REMAIN} - 1 `
done