Add ability to use random data or zeroes
This commit is contained in:
@@ -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
@@ -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"
|
||||||
Reference in New Issue
Block a user