first commit
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env bash
|
||||
# Overwrite partition-table and ZFS vdev-label metadata at both ends of a device.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
readonly PASSES=10
|
||||
readonly MIB=$((1024 * 1024))
|
||||
readonly WIPE_MIB=4
|
||||
readonly WIPE_BYTES=$((WIPE_MIB * MIB))
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: sudo ./erase-zfs-metadata.sh /dev/<device>
|
||||
|
||||
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.
|
||||
The device must not be mounted or part of an imported ZFS pool.
|
||||
EOF
|
||||
}
|
||||
|
||||
die() {
|
||||
printf 'Error: %s\n' "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
[[ $# -eq 1 ]] || { usage >&2; exit 2; }
|
||||
device=$1
|
||||
|
||||
[[ $EUID -eq 0 ]] || die 'run as root (for example, with sudo).'
|
||||
[[ -b $device ]] || die "'$device' is not a block device."
|
||||
|
||||
for command in blockdev dd findmnt lsblk zpool; do
|
||||
command -v "$command" >/dev/null 2>&1 || die "required command '$command' was not found."
|
||||
done
|
||||
|
||||
if findmnt --noheadings --source "$device" >/dev/null 2>&1; then
|
||||
die "'$device' is mounted; unmount it before continuing."
|
||||
fi
|
||||
|
||||
if lsblk --noheadings --raw --output MOUNTPOINT "$device" | grep -q '[^[:space:]]'; then
|
||||
die "'$device' or one of its children is mounted; unmount it before continuing."
|
||||
fi
|
||||
|
||||
if zpool status -P 2>/dev/null | grep -Fq -- "$device"; then
|
||||
die "'$device' belongs to an imported ZFS pool; export or detach it before continuing."
|
||||
fi
|
||||
|
||||
size_bytes=$(blockdev --getsize64 "$device")
|
||||
(( size_bytes >= 2 * WIPE_BYTES )) || die "'$device' is smaller than $((2 * WIPE_MIB)) MiB."
|
||||
|
||||
last_offset=$((size_bytes - WIPE_BYTES))
|
||||
|
||||
printf '\nWARNING: this permanently destroys partition tables and ZFS metadata on:\n %s\n\n' "$device"
|
||||
lsblk --output NAME,SIZE,TYPE,MOUNTPOINTS "$device"
|
||||
read -r -p "Type exactly 'ERASE $device' to continue: " confirmation
|
||||
[[ $confirmation == "ERASE $device" ]] || die 'confirmation did not match; no data was changed.'
|
||||
|
||||
for ((pass = 1; pass <= PASSES; pass++)); do
|
||||
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=/dev/zero of="$device" bs=1 count="$WIPE_BYTES" seek="$last_offset" conv=fsync,notrunc status=none
|
||||
done
|
||||
|
||||
sync
|
||||
printf 'Completed %d overwrite passes on %s.\n' "$PASSES" "$device"
|
||||
Reference in New Issue
Block a user