Add ability to use random data or zeroes

This commit is contained in:
2026-09-04 16:13:00 +03:00
parent 04c5e6cf12
commit 307aa55356
2 changed files with 64 additions and 9 deletions
+14 -2
View File
@@ -6,8 +6,9 @@ device after it has been cleanly removed from its pool.
## What It Erases ## What It Erases
The script performs 10 overwrite passes with zeroes over the first 4 MiB and The script performs 10 overwrite passes over the first 4 MiB and the last
the last 4 MiB of the target block device. These regions include: 4 MiB of the target block device. It uses zeroes by default and can use random
data when requested. These regions include:
- MBR data and GPT primary partition table at the beginning of a disk. - MBR data and GPT primary partition table at the beginning of a disk.
- GPT backup partition table at the end of a disk. - GPT backup partition table at the end of a disk.
@@ -41,6 +42,17 @@ chmod +x erase-zfs-metadata.sh
sudo ./erase-zfs-metadata.sh /dev/sdX sudo ./erase-zfs-metadata.sh /dev/sdX
``` ```
Use `--source random` to overwrite with data from `/dev/urandom` instead of
the default zeroes:
```bash
sudo ./erase-zfs-metadata.sh --source random /dev/sdX
```
The only accepted source values are `zeroes` and `random`. Random overwrites
are typically slower and do not erase additional parts of the device; both
modes overwrite the same first and last 4 MiB regions.
Replace `/dev/sdX` with the actual device, such as `/dev/sdb`, Replace `/dev/sdX` with the actual device, such as `/dev/sdb`,
`/dev/nvme0n1`, or a device-mapper path. Do not use the disk containing the `/dev/nvme0n1`, or a device-mapper path. Do not use the disk containing the
running system. running system.
+50 -7
View File
@@ -10,11 +10,16 @@ readonly WIPE_BYTES=$((WIPE_MIB * MIB))
usage() { usage() {
cat <<'EOF' cat <<'EOF'
Usage: sudo ./erase-zfs-metadata.sh /dev/<device> Usage: sudo ./erase-zfs-metadata.sh [--source zeroes|random] /dev/<device>
Overwrites the first and last 4 MiB of the specified block device ten times. Overwrites the first and last 4 MiB of the specified block device ten times.
This destroys MBR/GPT partition tables and all conventional ZFS vdev labels. This destroys MBR/GPT partition tables and all conventional ZFS vdev labels.
The device must not be mounted or part of an imported ZFS pool. The device must not be mounted or part of an imported ZFS pool.
Options:
--source zeroes Write zeroes from /dev/zero (default).
--source random Write random data from /dev/urandom.
-h, --help Show this help message.
EOF EOF
} }
@@ -23,11 +28,49 @@ die() {
exit 1 exit 1
} }
[[ $# -eq 1 ]] || { usage >&2; exit 2; } write_source=/dev/zero
device=$1 source_name=zeroes
device=
while [[ $# -gt 0 ]]; do
case $1 in
--source)
[[ $# -ge 2 ]] || die '--source requires zeroes or random.'
case $2 in
zeroes)
write_source=/dev/zero
source_name=zeroes
;;
random)
write_source=/dev/urandom
source_name=random
;;
*)
die "invalid source '$2'; use zeroes or random."
;;
esac
shift 2
;;
-h|--help)
usage
exit 0
;;
-*)
die "unknown option '$1'."
;;
*)
[[ -z $device ]] || die 'specify exactly one block device.'
device=$1
shift
;;
esac
done
[[ -n $device ]] || { usage >&2; exit 2; }
[[ $EUID -eq 0 ]] || die 'run as root (for example, with sudo).' [[ $EUID -eq 0 ]] || die 'run as root (for example, with sudo).'
[[ -b $device ]] || die "'$device' is not a block device." [[ -b $device ]] || die "'$device' is not a block device."
[[ -r $write_source ]] || die "'$write_source' is not readable."
for command in blockdev dd findmnt lsblk zpool; do for command in blockdev dd findmnt lsblk zpool; do
command -v "$command" >/dev/null 2>&1 || die "required command '$command' was not found." command -v "$command" >/dev/null 2>&1 || die "required command '$command' was not found."
@@ -50,16 +93,16 @@ size_bytes=$(blockdev --getsize64 "$device")
last_offset=$((size_bytes - WIPE_BYTES)) last_offset=$((size_bytes - WIPE_BYTES))
printf '\nWARNING: this permanently destroys partition tables and ZFS metadata on:\n %s\n\n' "$device" printf '\nWARNING: this permanently destroys partition tables and ZFS metadata on:\n %s\nusing %s data.\n\n' "$device" "$source_name"
lsblk --output NAME,SIZE,TYPE,MOUNTPOINTS "$device" lsblk --output NAME,SIZE,TYPE,MOUNTPOINTS "$device"
read -r -p "Type exactly 'ERASE $device' to continue: " confirmation read -r -p "Type exactly 'ERASE $device' to continue: " confirmation
[[ $confirmation == "ERASE $device" ]] || die 'confirmation did not match; no data was changed.' [[ $confirmation == "ERASE $device" ]] || die 'confirmation did not match; no data was changed.'
for ((pass = 1; pass <= PASSES; pass++)); do for ((pass = 1; pass <= PASSES; pass++)); do
printf 'Pass %d/%d...\n' "$pass" "$PASSES" printf 'Pass %d/%d...\n' "$pass" "$PASSES"
dd if=/dev/zero of="$device" bs="$MIB" count="$WIPE_MIB" conv=fsync,notrunc status=none dd if="$write_source" of="$device" bs="$MIB" count="$WIPE_MIB" conv=fsync,notrunc status=none
dd if=/dev/zero of="$device" bs=1 count="$WIPE_BYTES" seek="$last_offset" conv=fsync,notrunc status=none dd if="$write_source" of="$device" bs=1 count="$WIPE_BYTES" seek="$last_offset" conv=fsync,notrunc status=none
done done
sync sync
printf 'Completed %d overwrite passes on %s.\n' "$PASSES" "$device" printf 'Completed %d %s overwrite passes on %s.\n' "$PASSES" "$source_name" "$device"