saving files

This commit is contained in:
2026-08-06 10:52:53 -06:00
commit b0348ea45d
6 changed files with 1393 additions and 0 deletions
Executable
+80
View File
@@ -0,0 +1,80 @@
#!/usr/bin/env python3
import os
import sys
import re
# Physical mapping updated to 1-based indexing: (Row 1-6, Column 1-4)
BAY_MAP = {
"0000:01": {
"phy0": (1, 1), "phy1": (1, 2), "phy2": (1, 3), "phy3": (1, 4),
"phy4": (2, 1), "phy5": (2, 2), "phy6": (2, 3), "phy7": (2, 4),
},
"0000:02": {
"phy0": (3, 4), "phy1": (3, 3), "phy2": (3, 2), "phy3": (3, 1),
"phy4": (4, 4), "phy5": (4, 3), "phy6": (4, 2), "phy7": (4, 1),
},
"0000:04": {
"phy0": (5, 4), "phy1": (5, 3), "phy2": (5, 2), "phy3": (5, 1),
"phy4": (6, 4), "phy5": (6, 3), "phy6": (6, 2), "phy7": (6, 1),
}
}
def main():
export_mapping = (len(sys.argv) > 1 and sys.argv[1] == "--mapping")
# Initialize a 6x4 empty grid (1-indexed rows 1-6, columns 1-4)
# We use size 7x5 internally so we can just use the indices 1 to 6 and 1 to 4 directly
grid = [["[ EMPTY ]" for _ in range(5)] for _ in range(7)]
path_dir = "/dev/disk/by-path"
if not os.path.exists(path_dir):
if not export_mapping:
print(f"Error: {path_dir} does not exist.")
return
sas_regex = re.compile(r"pci-(0000:\d{2}):\d{2}\.\d-sas-(phy\d)-lun-0")
mappings = {}
for filename in os.listdir(path_dir):
match = sas_regex.match(filename)
if match:
pci_addr = match.group(1)
phy_id = match.group(2)
if pci_addr in BAY_MAP and phy_id in BAY_MAP[pci_addr]:
row, col = BAY_MAP[pci_addr][phy_id]
full_path = os.path.join(path_dir, filename)
try:
target = os.readlink(full_path)
dev_name = os.path.basename(target)
grid[row][col] = f"[ /dev/{dev_name} ]"
mappings[dev_name] = f"R{row}-C{col}"
except OSError:
grid[row][col] = "[ ERROR ]"
# Bash Mode: Output "sda:R1-C3" format
if export_mapping:
for dev, bay in mappings.items():
print(f"{dev}:{bay}")
return
# Visual Mode: Print your layout chart for the operators
print("\n" + "="*53)
print(" DRIVE WIPING BAY LAYOUT ")
print("="*53)
# Iterate from Row 1 to 6
for row_idx in range(1, 7):
# Slice columns 1 through 4
row_cells = grid[row_idx][1:5]
row_str = " | ".join(f"{cell:<11}" for cell in row_cells)
print(f"Row {row_idx}: | {row_str} |")
# Add visual separation between shelf units
if row_idx in [2, 4]:
print("-" * 53)
print("="*53 + "\n")
if __name__ == "__main__":
main()
+54
View File
@@ -0,0 +1,54 @@
(pkgs.writeShellScriptBin "wipe" ''
echo "Detecting in 15 seconds..."
sleep 10
echo 1 > /sys/bus/pci/rescan
sleep 5
if [ ! -e "/dev/nvme0n1" ]; then
echo "Rebooting in 3 seconds. If still not detected, NVMe is DOA."
sleep 3
reboot
else
echo "NVMe detected!"
fi
mkdir -p "/home/nps/logs"
SN="$(nvme id-ctrl /dev/nvme0n1 | awk '/^[[:space:]]*sn[[:space:]]*:/ {print $3; exit}')"
LOG_FILE="/home/nps/logs/$SN.log"
touch "$LOG_FILE"
echo "Wiping NVMe..."
nvme format /dev/nvme0n1 --ses=1 --force | tee "$LOG_FILE"
WIPE_STATUS=''${PIPESTATUS[0]}
smartctl -a /dev/nvme0n1 | tee -a "$LOG_FILE"
SMART_STATUS=''${PIPESTATUS[0]}
echo "Resetting parent PCIe bridge ($PARENT_BRIDGE) resources to disconnect NVMe in 15 seconds..."
echo 1 > "/sys/bus/pci/devices/0000:09:00.0/remove"
sleep 15
echo "NVMe disconnected and is safe to remove."
echo ""
# --- Final Confirmation ---
echo "==================================="
echo " RESULTS SUMMARY "
echo "==================================="
if [ "$WIPE_STATUS" -eq 0 ]; then
echo "WIPE: [ SUCCESS ]"
else
echo "WIPE: [ FAILED ]"
fi
if [ "$SMART_STATUS" -eq 0 ]; then
echo "SMART: [ PASSED ]"
else
echo "SMART: [ FAILED ]"
fi
echo "==================================="
'')
Executable
+379
View File
@@ -0,0 +1,379 @@
CONFIG_FILE="/home/nps/.config/wipe.conf" # Configuration file location. DO NOT CHANGE!
EXCLUDE_DEVICE="/dev/nvme0n1" # Boot drive, should not be changed. DO NOT CHANGE!
BUS_TYPE="" # NVMe wipe protocol by default.
MEDIA_TYPE="" # SSD by default.
DEVICE="" # Default device
LOG_FILE=""
wipe-confirmation() {
local wipe_status="$1"
local smart_status="$2"
if [ "$wipe_status" -eq 0 ]; then
wipe_status="WIPE: [ SUCCESS ]"
else
wipe_status="WIPE: [ FAILED ]"
fi
if [ "$smart_status" -eq 0 ]; then
smart_status="SMART: [ PASSED ]"
else
smart_status="SMART: [ FAILED ]"
fi
{ echo "
===================================
RESULTS SUMMARY
===================================
$wipe_status
$smart_status
===================================
"; cat "$LOG_FILE"; } > tmp.log && mv tmp.log $LOG_FILE
echo "
===================================
RESULTS SUMMARY
===================================
$wipe_status
$smart_status
===================================
"
}
smart-info() {
smartctl -a "$DEVICE" >> "$LOG_FILE" 2>&1
return ${PIPESTATUS[0]}
}
init-log() {
mkdir -p "/home/nps/logs"
SN="$(smartctl -a "$DEVICE" | awk '/Serial Number:/ {print $3; exit}')"
LOG_FILE="/home/nps/logs/$SN.log"
echo "" > "$LOG_FILE"
}
verify-wipe() {
local wipe_status
echo "Verifying wipe..." | tee -a "$LOG_FILE"
sleep 2
if dd if="$DEVICE" bs=1M count=1024 status=none | cmp -n 1073741824 -l - /dev/zero; then
echo "Verification passed." | tee -a "$LOG_FILE"
wipe_status=0
else
echo "Verification failed." | tee -a "$LOG_FILE"
wipe_status=1
fi
return "$wipe_status"
}
# Returns 0 if ready, 1 if unsupported, 2 if frozen/aborted.
sata-ssd-security-state() {
local status
status=$(sudo hdparm -I "$DEVICE")
# Check if supported
if ! echo "$status" | grep -q "supported"; then
echo "Error: Drive does not support ATA security features."
return 1 # Unsupported
fi
# Check if frozen
if echo "$status" | grep -q "frozen" | grep -v -q "not"; then
echo "Error: Drive is in a 'frozen' state. Hot-plug required."
read -p "Has drive been hot-plugged? (y/N)" -r -n 1
echo
if [[ "$REPLY" =~ ^[Yy]$ ]]; then
sata-ssd-security-state
return $?
fi
return 2 # Frozen/aborted by user.
fi
return 0 # Ready
}
wipe-sata-ssd() {
local wipe_status
echo "Checking security state..."
sata-ssd-security-state
local state=$?
case $state in
"0")
echo "Executing ATA Secure Erase..." | tee -a "$LOG_FILE"
hdparm --user-master u --security-set-pass p "$DEVICE" >> "$LOG_FILE" 2>&1
hdparm --user-master u --security-erase p "$DEVICE" >> "$LOG_FILE" 2>&1
wipe_status=$?
;;
"1")
echo "ATA Security not supported. Falling back to blkdiscard..." | tee -a "$LOG_FILE"
blkdiscard --secure "$DEVICE" >> "$LOG_FILE" 2>&1
wipe_status=$?
;;
"2")
echo "Aborted: Drive is frozen or user declined hot-plug."
return 2
;;
*)
echo "Unknown state returned."
return 1
;;
esac
if [ $wipe_status -eq 0 ]; then
blockdev --rereadpt "$DEVICE"
partprobe "$DEVICE"
udevadm settle
verify-wipe
wipe_status=$?
fi
# Write SMART info to LOG and save result for confirmation display.
smart-info
wipe-confirmation "$wipe_status" "$?"
echo -e "\n\nSATA SSD wipe complete and ready to remove."
}
wipe-hdd() {
echo "Wiping HDD..." | tee -a "$LOG_FILE"
shred -vz -n 1 "$DEVICE"
local wipe_status=$?
if [ $wipe_status -eq 0 ]; then
verify-wipe
wipe_status=$?
fi
# Write SMART info to LOG and save result for confirmation display.
smart-info
wipe-confirmation "$wipe_status" "$?"
echo -e "\n\nHDD wipe complete and ready to remove."
}
wipe-emmc() {
echo "Wiping eMMC..." | tee -a "$LOG_FILE"
blkdiscard "$DEVICE" >> "$LOG_FILE" 2>&1
local wipe_status=$?
if [ $wipe_status -eq 0 ]; then
verify-wipe
wipe_status=$?
fi
# Write SMART info to LOG and save result for confirmation display.
smart-info
wipe-confirmation "$wipe_status" "$?"
echo -e "\n\neMMC wipe complete and ready to remove."
}
wipe-usb() {
echo "Wiping USB..." | tee -a "$LOG_FILE"
shred -vz -n 1 "$DEVICE"
local wipe_status=$?
if [ $wipe_status -eq 0 ]; then
verify-wipe
wipe_status=$?
fi
# Write SMART info to LOG and save result for confirmation display.
smart-info
wipe-confirmation "$wipe_status" "$?"
echo -e "\n\nUSB wipe complete and ready to remove."
}
wipe-nvme() {
# Wipe NVMe via Secure Erase NVMe feature.
echo "Wiping NVMe..."
nvme format "$DEVICE" --ses=1 --force >> "$LOG_FILE" 2>&1
local wipe_status=$?
# Write SMART info to LOG and save result for confirmation display.
smart-info
local smart_status=$?
# Dynamic disconnect of NVMe drive
local dev_node="${DEVICE#/dev/}"
local pci_path=$(readlink -f "/sys/block/$dev_node/device" | xargs basename)
echo "NVMe disconnect will take 15 seconds..."
echo 1 > "/sys/bus/pci/devices/$pci_path/remove"
sleep 15
wipe-confirmation "$wipe_status" "$smart_status"
echo -e "\n\nNVMe disconnected and is safe to remove."
}
show-help() {
echo '
Created by Josh Ashton
Last modified: 20-07-2026
Email: me@joshashton.dev
Secondary Email: joshua.ashton@npsstore.com
Drive wiping utility for various drive types.
Usage:
- `wipe`
Use default wipe method (NVMe SSD format)
- `wipe -h` & `wipe --help`
Show this help page.
Cannot be combined with other arguments.
- `wipe -b nvme` & `wipe --bus-type nvme`
Set the bus type that a drive is connected to (ie. nvme, sata). nvme is
the default bus type. And will automatically set the media type to SSD.
Use without providing a bus type to list available bus types.
- `wipe -m ssd` & `wipe --media-type ssd`
Set the media type to wipe (ie. ssd, hdd, emmc, usb). ssd is the
default media type.
Use without providing a media type to list available media types.
- `wipe -d /dev/nvme0n1` & `wipe --device /dev/nvme0n1`
Set the device to wipe. Defaults to the first device of the bus type.
Use without providing a device to list available devices.
- `wipe -c` & `wipe --configure`
Perform guided configuration to set new defaults. Changes are persistent
and can be directly edited at `$HOME/.config/wipe.conf`.
Cannot be combined with other arguments.
Arguments can be combined for more control:
- `wipe -b sata -m hdd -d /dev/sdb`
'
exit
}
detect-device() {
if [[ "$BUS_TYPE" == "nvme" ]]; then
echo "Detecting in 15 seconds..."
sleep 10
echo 1 > /sys/bus/pci/rescan
sleep 5
if [ ! -e "$DEVICE" ]; then
echo "Rebooting in 3 seconds. If still not detected, NVMe is DOA."
sleep 3
reboot
else
echo "NVMe detected!"
fi
elif [[ "$BUS_TYPE" == "sata" && "$MEDIA_TYPE" == "ssd" ]]; then
udevadm trigger
if [ ! -e "$DEVICE" ]; then
echo "Drive is DOA."
exit 1
fi
fi
init-log
}
run-wipe() {
# Safety check
if [[ "$DEVICE" == "$EXCLUDE_DEVICE" ]] || grep -q "$DEVICE" /proc/mounts; then
echo "CRITICAL ERROR: Attempted to wipe protected or mounted device: $DEVICE"
exit 1
fi
case "$BUS_TYPE:$MEDIA_TYPE" in
nvme:ssd) wipe-nvme ;;
sata:ssd) wipe-sata-ssd ;;
*:hdd) wipe-hdd ;;
*:emmc) wipe-emmc ;;
*:usb) wipe-usb ;;
*) echo "Unsupported configuration: $BUS_TYPE/$MEDIA_TYPE"; exit 1 ;;
esac
}
configure-wipe() {
# 1. Select Bus Type
BUS_TYPE=$(dialog --title "Bus Type" --menu "Select bus type:" 15 60 4 \
"nvme" "NVMe Drive" \
"sata" "SATA Drive" \
"usb" "USB Storage" 3>&1 1>&2 2>&3) || exit
# 2. Select Media Type
MEDIA_TYPE=$(dialog --title "Media Type" --menu "Select media type:" 15 60 4 \
"ssd" "Solid State Drive" \
"hdd" "Hard Disk Drive" \
"emmc" "eMMC Flash" 3>&1 1>&2 2>&3) || exit
# 3. Select Device (Dynamic list of block devices)
local dev_list=()
while read -r dev; do
dev_list+=("$dev" "Available device")
done < <(lsblk -dpno NAME | grep -v "$EXCLUDE_DEVICE")
if [ "${#dev_list[@]}" -eq 0 ]; then
dialog --msgbox "No available drives detected." 8 40
clear
exit 1
fi
DEVICE=$(dialog --title "Device Selection" --menu "Select device to wipe:" 15 60 10 \
"${dev_list[@]}" 3>&1 1>&2 2>&3) || exit
# 4. Save to Config
mkdir -p "$(dirname "$CONFIG_FILE")"
echo "
BUS_TYPE=$BUS_TYPE
MEDIA_TYPE=$MEDIA_TYPE
DEVICE=$DEVICE
" > "$CONFIG_FILE"
dialog --msgbox "Configuration saved to $CONFIG_FILE" 8 40
clear
exit 0
}
main() {
local GETOPT_BIN="/run/current-system/sw/bin/getopt"
[ -f "$CONFIG_FILE" ] && source "$CONFIG_FILE"
local OPTS
OPTS=$("$GETOPT_BIN" -o b:m:d:hc -l bus-type:,media-type:,device:,help,configure -- "$@")
if [ $? -ne 0 ]; then help; exit 1; fi
eval set -- "$OPTS"
while true; do
case "$1" in
-b|--bus-type) BUS_TYPE="$2"; shift 2 ;;
-m|--media-type) MEDIA_TYPE="$2"; shift 2 ;;
-d|--device) DEVICE="$2"; shift 2 ;;
-h|--help) show-help ;;
-c|--configure) configure-wipe ;;
--) shift; break ;;
*) echo "Unexpected error"; help; exit 1 ;;
esac
done
if [[ -z "$DEVICE" ]]; then
echo "Error: No device specified. Use -d or run -c to configure."
exit 1
fi
init-log
detect-device
run-wipe
}
main "$@"
Executable
+412
View File
@@ -0,0 +1,412 @@
#!/bin/sh
CONFIG_FILE="/home/nps/.config/wipe.conf" # Configuration file location. DO NOT CHANGE!
EXCLUDE_DEVICE="/dev/nvme0n1" # Boot drive, should not be changed. DO NOT CHANGE!
BUS_TYPE="" # NVMe wipe protocol by default.
MEDIA_TYPE="" # SSD by default.
DEVICE="" # Default device
LOG_FILE=""
wipe-confirmation() {
local wipe_status="$1"
local smart_status="$2"
if [ "$wipe_status" -eq 0 ]; then
wipe_status="WIPE: [ SUCCESS ]"
else
wipe_status="WIPE: [ FAILED ]"
fi
if [ $(("$smart_status" & 24)) -eq 0 ] || "$smart_status" -eq 0; then
smart_status="SMART: [ PASSED ]"
else
smart_status="SMART: [ FAILED ]"
fi
{ echo "
===================================
RESULTS SUMMARY
===================================
$wipe_status
$smart_status
===================================
"; cat "$LOG_FILE"; } > tmp.log && mv tmp.log $LOG_FILE
echo "
===================================
RESULTS SUMMARY
===================================
$wipe_status
$smart_status
===================================
"
}
smart-info() {
if [[ "$BUS_TYPE" == "usb" ]]; then
smartctl -d sat -x "$DEVICE" >> "$LOG_FILE" 2>&1
else
smartctl -a "$DEVICE" >> "$LOG_FILE" 2>&1
fi
return ${PIPESTATUS[0]}
}
init-log() {
mkdir -p "/home/nps/logs"
if [ "$BUS_TYPE" == "usb" ]; then
SN="$(lsblk -no NAME,SERIAL | grep sda | head -n 1 | awk '{print $2}')"
else
SN="$(smartctl -a "$DEVICE" | awk '/Serial Number:/ {print $3; exit}')"
fi
LOG_FILE="/home/nps/logs/$SN.log"
echo "" > "$LOG_FILE"
}
verify-wipe() {
local wipe_status
echo "Verifying wipe..." | tee -a "$LOG_FILE"
sleep 2
if dd if="$DEVICE" bs=1M count=1024 status=none | cmp -n 1073741824 -l - /dev/zero; then
echo "Verification passed." | tee -a "$LOG_FILE"
wipe_status=0
else
echo "Verification failed." | tee -a "$LOG_FILE"
wipe_status=1
fi
return "$wipe_status"
}
# Returns 0 if ready, 1 if unsupported, 2 if frozen/aborted.
sata-ssd-security-state() {
local status
status=$(sudo hdparm -I "$DEVICE")
# Check if supported
if ! echo "$status" | grep -q "supported"; then
echo "Error: Drive does not support ATA security features."
return 1 # Unsupported
fi
# Check if frozen
if echo "$status" | grep -q "frozen" | grep -v -q "not"; then
echo "Error: Drive is in a 'frozen' state. Hot-plug required."
read -p "Has drive been hot-plugged? (y/N)" -r -n 1
echo
if [[ "$REPLY" =~ ^[Yy]$ ]]; then
sata-ssd-security-state
return $?
fi
return 2 # Frozen/aborted by user.
fi
return 0 # Ready
}
wipe-sata-ssd() {
local wipe_status
echo "Checking security state..."
sata-ssd-security-state
local state=$?
case $state in
"0")
echo "Executing ATA Secure Erase..." | tee -a "$LOG_FILE"
hdparm --user-master u --security-set-pass p "$DEVICE" >> "$LOG_FILE" 2>&1
hdparm --user-master u --security-erase p "$DEVICE" >> "$LOG_FILE" 2>&1
wipe_status=$?
;;
"1")
echo "ATA Security not supported. Falling back to blkdiscard..." | tee -a "$LOG_FILE"
blkdiscard --secure "$DEVICE" >> "$LOG_FILE" 2>&1
wipe_status=$?
;;
"2")
echo "Aborted: Drive is frozen or user declined hot-plug."
return 2
;;
*)
echo "Unknown state returned."
return 1
;;
esac
if [ $wipe_status -eq 0 ]; then
blockdev --rereadpt "$DEVICE"
partprobe "$DEVICE"
udevadm settle
verify-wipe
wipe_status=$?
fi
# Write SMART info to LOG and save result for confirmation display.
smart-info
wipe-confirmation "$wipe_status" "$?"
echo -e "\n\nSATA SSD wipe complete and ready to remove."
}
wipe-hdd() {
echo "Wiping HDD..." | tee -a "$LOG_FILE"
shred -vz -n 1 "$DEVICE"
local wipe_status=$?
if [ $wipe_status -eq 0 ]; then
verify-wipe
wipe_status=$?
fi
# Write SMART info to LOG and save result for confirmation display.
smart-info
wipe-confirmation "$wipe_status" "$?"
echo -e "\n\nHDD wipe complete and ready to remove."
}
wipe-emmc() {
echo "Wiping eMMC..." | tee -a "$LOG_FILE"
blkdiscard "$DEVICE" >> "$LOG_FILE" 2>&1
local wipe_status=$?
if [ $wipe_status -eq 0 ]; then
verify-wipe
wipe_status=$?
fi
# Write SMART info to LOG and save result for confirmation display.
smart-info
wipe-confirmation "$wipe_status" "$?"
echo -e "\n\neMMC wipe complete and ready to remove."
}
wipe-usb() {
local raw_device="${DEVICE#/dev/}"
local kernel_mode=$(cat /sys/block/$raw_device/device/scsi_disk/*/provisioning_mode)
local wipe_status=4
if $(sg_vpd --all "$DEVICE" | grep -q "LBPU=1") || [[ "$kernel_mode" == "unmap" ]]; then
if [ "$kernel_mode" != "unmap" ]; then
echo "USB device supports UNMAP/TRIM mode, attempting to update provisioning mode..." | tee -a "$LOG_FILE"
echo "unmap" | tee "/sys/block/$raw_device/device/scsi_disk/*/provisioning_mode"
fi
echo "Wiping USB via built-in UNMAP/TRIM mode..." | tee -a "$LOG_FILE"
blkdiscard "$DEVICE"
wipe_status=$?
if [ $wipe_status != 0 ]; then
echo "UNMAP/TRIM mode wipe failed!"
fi
fi
if [[ "$kernel_mode" == "full" || $wipe_status -ne 0 ]]; then
echo "USB device doesn't support UNMAP/TRIM mode, falling back to dd." | tee -a "$LOG_FILE"
dd if=/dev/zero of="$DEVICE" bs=4M status=progress conv=fdatasync 2>&1 | tee -a "$LOG_FILE"
wipe_status=${PIPESTATUS[0]}
fi
if [ $wipe_status -eq 0 ]; then
verify-wipe
wipe_status=$?
fi
# Write SMART info to LOG and save result for confirmation display.
smart-info
wipe-confirmation "$wipe_status" "$?"
echo -e "\n\nUSB wipe complete and ready to remove."
}
wipe-nvme() {
# Wipe NVMe via Secure Erase NVMe feature.
echo "Wiping NVMe..."
nvme format "$DEVICE" --ses=1 --force >> "$LOG_FILE" 2>&1
local wipe_status=$?
# Write SMART info to LOG and save result for confirmation display.
smart-info
local smart_status=$?
# Dynamic disconnect of NVMe drive
local dev_node="${DEVICE#/dev/}"
local pci_path=$(readlink -f "/sys/block/$dev_node/device" | xargs basename)
echo "NVMe disconnect will take 15 seconds..."
echo 1 > "/sys/bus/pci/devices/$pci_path/remove"
sleep 15
wipe-confirmation "$wipe_status" "$smart_status"
echo -e "\n\nNVMe disconnected and is safe to remove."
}
show-help() {
echo '
Created by Josh Ashton
Last modified: 20-07-2026
Email: me@joshashton.dev
Secondary Email: joshua.ashton@npsstore.com
Drive wiping utility for various drive types.
Usage:
- `wipe`
Use default wipe method (NVMe SSD format)
- `wipe -h` & `wipe --help`
Show this help page.
Cannot be combined with other arguments.
- `wipe -b nvme` & `wipe --bus-type nvme`
Set the bus type that a drive is connected to (ie. nvme, sata). nvme is
the default bus type. And will automatically set the media type to SSD.
Use without providing a bus type to list available bus types.
- `wipe -m ssd` & `wipe --media-type ssd`
Set the media type to wipe (ie. ssd, hdd, emmc, usb). ssd is the
default media type.
Use without providing a media type to list available media types.
- `wipe -d /dev/nvme0n1` & `wipe --device /dev/nvme0n1`
Set the device to wipe. Defaults to the first device of the bus type.
Use without providing a device to list available devices.
- `wipe -c` & `wipe --configure`
Perform guided configuration to set new defaults. Changes are persistent
and can be directly edited at `$HOME/.config/wipe.conf`.
Cannot be combined with other arguments.
Arguments can be combined for more control:
- `wipe -b sata -m hdd -d /dev/sdb`
'
exit
}
detect-device() {
if [[ "$BUS_TYPE" == "nvme" ]]; then
echo "Detecting in 15 seconds..."
sleep 10
echo 1 > /sys/bus/pci/rescan
sleep 5
if [ ! -e "$DEVICE" ]; then
echo "Rebooting in 3 seconds. If still not detected, NVMe is DOA."
sleep 3
reboot
else
echo "NVMe detected!"
fi
elif [[ "$BUS_TYPE" == "sata" && "$MEDIA_TYPE" == "ssd" ]]; then
udevadm trigger
if [ ! -e "$DEVICE" ]; then
echo "Drive is DOA."
exit 1
fi
fi
init-log
}
run-wipe() {
# Safety check
if [[ "$DEVICE" == "$EXCLUDE_DEVICE" ]] || grep -q "$DEVICE" /proc/mounts; then
echo "CRITICAL ERROR: Attempted to wipe protected or mounted device: $DEVICE"
exit 1
fi
case "$BUS_TYPE:$MEDIA_TYPE" in
nvme:ssd) wipe-nvme ;;
sata:ssd) wipe-sata-ssd ;;
*:hdd) wipe-hdd ;;
*:emmc) wipe-emmc ;;
usb:*) wipe-usb ;;
*) echo "Unsupported configuration: $BUS_TYPE/$MEDIA_TYPE"; exit 1 ;;
esac
}
configure-wipe() {
# 1. Select Bus Type
BUS_TYPE=$(dialog --title "Bus Type" --menu "Select bus type:" 15 60 4 \
"nvme" "NVMe Drive" \
"sata" "SATA Drive" \
"usb" "USB Storage" 3>&1 1>&2 2>&3) || exit
# 2. Select Media Type
MEDIA_TYPE=$(dialog --title "Media Type" --menu "Select media type:" 15 60 4 \
"ssd" "Solid State Drive" \
"hdd" "Hard Disk Drive" \
"emmc" "eMMC Flash" 3>&1 1>&2 2>&3) || exit
# 3. Select Device (Dynamic list of block devices)
local dev_list=()
while read -r dev; do
dev_list+=("$dev" "Available device")
done < <(lsblk -dpno NAME | grep -v "$EXCLUDE_DEVICE")
if [ "${#dev_list[@]}" -eq 0 ]; then
dialog --msgbox "No available drives detected." 8 40
clear
exit 1
fi
DEVICE=$(dialog --title "Device Selection" --menu "Select device to wipe:" 15 60 10 \
"${dev_list[@]}" 3>&1 1>&2 2>&3) || exit
# 4. Save to Config
mkdir -p "$(dirname "$CONFIG_FILE")"
echo "
BUS_TYPE=$BUS_TYPE
MEDIA_TYPE=$MEDIA_TYPE
DEVICE=$DEVICE
" > "$CONFIG_FILE"
dialog --msgbox "Configuration saved to $CONFIG_FILE" 8 40
clear
exit 0
}
main() {
local GETOPT_BIN="/run/current-system/sw/bin/getopt"
[ -f "$CONFIG_FILE" ] && source "$CONFIG_FILE"
local OPTS
OPTS=$("$GETOPT_BIN" -o b:m:d:hc -l bus-type:,media-type:,device:,help,configure -- "$@")
if [ $? -ne 0 ]; then help; exit 1; fi
eval set -- "$OPTS"
while true; do
case "$1" in
-b|--bus-type) BUS_TYPE="$2"; shift 2 ;;
-m|--media-type) MEDIA_TYPE="$2"; shift 2 ;;
-d|--device) DEVICE="$2"; shift 2 ;;
-h|--help) show-help ;;
-c|--configure) configure-wipe ;;
--) shift; break ;;
*) echo "Unexpected error"; help; exit 1 ;;
esac
done
if [[ -z "$DEVICE" ]]; then
echo "Error: No device specified. Use -d or run -c to configure."
exit 1
fi
init-log
detect-device
run-wipe
}
main "$@"
Executable
+370
View File
@@ -0,0 +1,370 @@
CONFIG_FILE="$HOME/.config/wipe.conf" # Configuration file location. DO NOT CHANGE!
EXCLUDE_DEVICE="/dev/sda" # Boot drive, should not be changed. DO NOT CHANGE!
BUS_TYPE="" # NVMe wipe protocol by default.
MEDIA_TYPE="" # SSD by default.
DEVICE="" # Default device
LOG_FILE=""
wipe-confirmation() {
local wipe_status="$1"
local smart_status="$2"
if [ "$wipe_status" -eq 0 ]; then
wipe_status="WIPE: [ SUCCESS ]"
else
wipe_status="WIPE: [ FAILED ]"
fi
if [ "$smart_status" -eq 0 ]; then
smart_status="SMART: [ PASSED ]"
else
smart_status="SMART: [ FAILED ]"
fi
{ echo "
===================================
RESULTS SUMMARY
===================================
$wipe_status
$smart_status
===================================
"; cat "$LOG_FILE"; } > tmp.log && mv tmp.log $LOG_FILE
echo "
===================================
RESULTS SUMMARY
===================================
$wipe_status
$smart_status
===================================
"
}
smart-info() {
smartctl -a "$DEVICE" >> "$LOG_FILE" 2>&1
return ${PIPESTATUS[0]}
}
init-log() {
mkdir -p "/home/nps/logs"
SN="$(smartctl -a "$DEVICE" | awk '/Serial Number:/ {print $3; exit}')"
LOG_FILE="/home/nps/logs/$SN.log"
echo "" > "$LOG_FILE"
}
verify-wipe() {
local wipe_status
echo "Verifying wipe..." | tee -a "$LOG_FILE"
sleep 2
if dd if="$DEVICE" bs=1M count=1024 status=none | cmp -s - /dev/zero; then
echo "Verification passed." | tee -a "$LOG_FILE"
wipe_status=0
else
echo "Verification failed." | tee -a "$LOG_FILE"
wipe_status=1
fi
return "$wipe_status"
}
# Returns 0 if ready, 1 if unsupported, 2 if frozen/aborted.
sata-ssd-security-state() {
local status
status=$(sudo hdparm -I "$DEVICE")
# Check if supported
if ! echo "$status" | grep -q "supported"; then
echo "Error: Drive does not support ATA security features."
return 1 # Unsupported
fi
# Check if frozen
if echo "$status" | grep -q "frozen"; then
echo "Error: Drive is in a 'frozen' state. Hot-plug required."
read -p "Has drive been hot-plugged? (y/N)" -r -n 1
echo
if [[ "$REPLY" =~ ^[Yy]$ ]]; then
sata-ssd-security-state
return $?
fi
return 2 # Frozen/aborted by user.
fi
return 0 # Ready
}
wipe-sata-ssd() {
local wipe_status
echo "Checking security state..."
sata-ssd-security-state
local state=$?
case $state in
"0")
echo "Executing ATA Secure Erase..." | tee -a "$LOG_FILE"
hdparm --user-master u --security-set-pass p "$DEVICE" >> "$LOG_FILE" 2>&1
hdparm --user-master u --security-erase p "$DEVICE" >> "$LOG_FILE" 2>&1
wipe_status=$?
;;
"1")
echo "ATA Security not supported. Falling back to blkdiscard..." | tee -a "$LOG_FILE"
blkdiscard --secure "$DEVICE" >> "$LOG_FILE" 2>&1
wipe_status=$?
;;
"2")
echo "Aborted: Drive is frozen or user declined hot-plug."
return 2
;;
*)
echo "Unknown state returned."
return 1
;;
esac
if [ $wipe_status -eq 0 ]; then
verify-wipe
wipe_status=$?
fi
# Write SMART info to LOG and save result for confirmation display.
smart-info
wipe-confirmation "$wipe_status" "$?"
echo -e "\n\nSATA SSD wipe complete and ready to remove."
}
wipe-hdd() {
echo "Wiping HDD..." | tee -a "$LOG_FILE"
shred -vz -n 1 "$DEVICE"
local wipe_status=$?
if [ $wipe_status -eq 0 ]; then
verify-wipe
wipe_status=$?
fi
# Write SMART info to LOG and save result for confirmation display.
smart-info
wipe-confirmation "$wipe_status" "$?"
echo -e "\n\nHDD wipe complete and ready to remove."
}
wipe-emmc() {
echo "Wiping eMMC..." | tee -a "$LOG_FILE"
blkdiscard "$DEVICE" >> "$LOG_FILE" 2>&1
local wipe_status=$?
if [ $wipe_status -eq 0 ]; then
verify-wipe
wipe_status=$?
fi
# Write SMART info to LOG and save result for confirmation display.
smart-info
wipe-confirmation "$wipe_status" "$?"
echo -e "\n\neMMC wipe complete and ready to remove."
}
wipe-usb() {
echo "Wiping USB..." | tee -a "$LOG_FILE"
shred -vz -n 1 "$DEVICE"
local wipe_status=$?
if [ $wipe_status -eq 0 ]; then
verify-wipe
wipe_status=$?
fi
# Write SMART info to LOG and save result for confirmation display.
smart-info
wipe-confirmation "$wipe_status" "$?"
echo -e "\n\nUSB wipe complete and ready to remove."
}
wipe-nvme() {
# Wipe NVMe via Secure Erase NVMe feature.
echo "Wiping NVMe..."
nvme format "$DEVICE" --ses=1 --force >> "$LOG_FILE" 2>&1
local wipe_status=$?
# Write SMART info to LOG and save result for confirmation display.
smart-info
local smart_status=$?
# Dynamic disconnect of NVMe drive
local dev_node="${DEVICE#/dev/}"
local pci_path=$(readlink -f "/sys/block/$dev_node/device" | xargs dirname | xargs dirname | xargs basename)
echo "NVMe disconnect will take 15 seconds..."
echo 1 > "/sys/bus/pci/devices/$pci_path/remove"
sleep 15
wipe-confirmation "$wipe_status" "$smart_status"
echo -e "\n\nNVMe disconnected and is safe to remove."
}
show-help() {
echo '
Created by Josh Ashton
Last modified: 20-07-2026
Email: me@joshashton.dev
Secondary Email: joshua.ashton@npsstore.com
Drive wiping utility for various drive types.
Usage:
- `wipe`
Use default wipe method (NVMe SSD format)
- `wipe -h` & `wipe --help`
Show this help page.
Cannot be combined with other arguments.
- `wipe -b nvme` & `wipe --bus-type nvme`
Set the bus type that a drive is connected to (ie. nvme, sata). nvme is
the default bus type. And will automatically set the media type to SSD.
Use without providing a bus type to list available bus types.
- `wipe -m ssd` & `wipe --media-type ssd`
Set the media type to wipe (ie. ssd, hdd, emmc, usb). ssd is the
default media type.
Use without providing a media type to list available media types.
- `wipe -d /dev/nvme0n1` & `wipe --device /dev/nvme0n1`
Set the device to wipe. Defaults to the first device of the bus type.
Use without providing a device to list available devices.
- `wipe -c` & `wipe --configure`
Perform guided configuration to set new defaults. Changes are persistent
and can be directly edited at `$HOME/.config/wipe.conf`.
Cannot be combined with other arguments.
Arguments can be combined for more control:
- `wipe -b sata -m hdd -d /dev/sdb`
'
exit
}
detect-device() {
if [[ "$BUS_TYPE" == "nvme" ]]; then
echo "Detecting in 15 seconds..."
sleep 10
echo 1 > /sys/bus/pci/rescan
sleep 5
if [ ! -e "$DEVICE" ]; then
echo "Rebooting in 3 seconds. If still not detected, NVMe is DOA."
sleep 3
reboot
else
echo "NVMe detected!"
fi
elif [[ "$BUS_TYPE" == "sata" && "$MEDIA_TYPE" == "ssd" ]]; then
echo "Detecting in 15 seconds..."
fi
init-log
}
run-wipe() {
# Safety check
if [[ "$DEVICE" == "$EXCLUDE_DEVICE" ]] || grep -q "$DEVICE" /proc/mounts; then
echo "CRITICAL ERROR: Attempted to wipe protected or mounted device: $DEVICE"
exit 1
fi
case "$BUS_TYPE:$MEDIA_TYPE" in
nvme:ssd) wipe-nvme ;;
sata:ssd) wipe-sata-ssd ;;
*:hdd) wipe-hdd ;;
*:emmc) wipe-emmc ;;
*:usb) wipe-usb ;;
*) echo "Unsupported configuration: $BUS_TYPE/$MEDIA_TYPE"; exit 1 ;;
esac
}
configure-wipe() {
# 1. Select Bus Type
BUS_TYPE=$(dialog --title "Bus Type" --menu "Select bus type:" 15 60 4 \
"nvme" "NVMe Drive" \
"sata" "SATA Drive" \
"usb" "USB Storage" 3>&1 1>&2 2>&3) || exit
# 2. Select Media Type
MEDIA_TYPE=$(dialog --title "Media Type" --menu "Select media type:" 15 60 4 \
"ssd" "Solid State Drive" \
"hdd" "Hard Disk Drive" \
"emmc" "eMMC Flash" 3>&1 1>&2 2>&3) || exit
# 3. Select Device (Dynamic list of block devices)
local dev_list=()
while read -r dev; do
dev_list+=("$dev" "Available device")
done < <(lsblk -dpno NAME | grep -v "$EXCLUDE_DEVICE")
if [ "${#dev_list[@]}" -eq 0 ]; then
dialog --msgbox "No available drives detected." 8 40
clear
exit 1
fi
DEVICE=$(dialog --title "Device Selection" --menu "Select device to wipe:" 15 60 10 \
"${dev_list[@]}" 3>&1 1>&2 2>&3) || exit
# 4. Save to Config
mkdir -p "$(dirname "$CONFIG_FILE")"
echo "
BUS_TYPE=$BUS_TYPE
MEDIA_TYPE=$MEDIA_TYPE
DEVICE=$DEVICE
" > "$CONFIG_FILE"
dialog --msgbox "Configuration saved to $CONFIG_FILE" 8 40
clear
exit 0
}
main() {
local GETOPT_BIN="/run/current-system/sw/bin/getopt"
[ -f "$CONFIG_FILE" ] && source "$CONFIG_FILE"
local OPTS
OPTS=$("$GETOPT_BIN" -o b:m:d:hc -l bus-type:,media-type:,device:,help,configure -- "$@")
if [ $? -ne 0 ]; then help; exit 1; fi
eval set -- "$OPTS"
while true; do
case "$1" in
-b|--bus-type) BUS_TYPE="$2"; shift 2 ;;
-m|--media-type) MEDIA_TYPE="$2"; shift 2 ;;
-d|--device) DEVICE="$2"; shift 2 ;;
-h|--help) show-help ;;
-c|--configure) configure-wipe ;;
--) shift; break ;;
*) echo "Unexpected error"; help; exit 1 ;;
esac
done
if [[ -z "$DEVICE" ]]; then
echo "Error: No device specified. Use -d or run -c to configure."
exit 1
fi
init-log
detect-device
run-wipe
}
main "$@"
Executable
+98
View File
@@ -0,0 +1,98 @@
#!/bin/bash
# Configuration
REPORT_DIR="/var/log/nwipe_reports"
WIPE_METHOD="dod3pass"
PYTHON_MAP_SCRIPT="/usr/local/bin/drive_map"
mkdir -p "$REPORT_DIR"
# ANSI Escape codes for colored text
GREEN='\033[0;32m'
CYAN='\033[0;36m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
clear
echo -e "${CYAN}=====================================================${NC}"
echo -e "${CYAN} NWIPE MULTI-DRIVE CONTROL PANEL ${NC}"
echo -e "${CYAN}=====================================================${NC}"
# 1. Print the visual layout map to the terminal first
if [ -f "$PYTHON_MAP_SCRIPT" ]; then
python3 "$PYTHON_MAP_SCRIPT"
else
echo "Warning: Python mapping script not found at $PYTHON_MAP_SCRIPT"
fi
# 2. Safely isolate the boot/OS disk
OS_DISK=$(lsblk -no PKNAME $(findmnt -no SOURCE /))
DRIVES=$(lsblk -dno NAME,TYPE | awk '$2=="disk" {print $1}')
# Associative arrays to track state
declare -A DRIVE_BAYS
declare -A DEPLOYED_DRIVES
echo -e "${YELLOW}Initializing independent background wipe tasks...${NC}"
for DISK in $DRIVES; do
if [ "$DISK" = "$OS_DISK" ]; then
continue
fi
# Fetch 1-indexed physical bay (e.g., R1-C3)
BAY_LOC=$(python3 "$PYTHON_MAP_SCRIPT" --mapping | grep "^${DISK}:" | cut -d':' -f2)
if [ -z "$BAY_LOC" ]; then
BAY_LOC="Unknown"
fi
# Store bay mapping for reporting
DRIVE_BAYS[$DISK]=$BAY_LOC
# Unique name for this drive's hidden tmux session
SESSION_NAME="hidden-wipe-${DISK}"
# Force kill any stale sessions for this disk if they exist
tmux kill-session -t "$SESSION_NAME" 2>/dev/null
# Command to run nwipe
NWIPE_CMD="sudo nwipe --autonuke --nowait --method=$WIPE_METHOD --PDFreportpath=$REPORT_DIR /dev/$DISK"
# Spawn the nwipe task completely hidden inside a detached tmux session
tmux new-session -d -s "$SESSION_NAME" "$NWIPE_CMD"
# Track that this drive is actively running
DEPLOYED_DRIVES[$DISK]="RUNNING"
echo " -> Drive /dev/$DISK ($BAY_LOC) started in background."
done
echo -e "\n${YELLOW}Monitoring drive progress. Do not close this terminal.${NC}"
echo -e "-----------------------------------------------------\n"
# 3. Live Monitoring Loop
while [ ${#DEPLOYED_DRIVES[@]} -gt 0 ]; do
sleep 3 # Check status every 3 seconds
for DISK in "${!DEPLOYED_DRIVES[@]}"; do
SESSION_NAME="hidden-wipe-${DISK}"
BAY=${DRIVE_BAYS[$DISK]}
# Check if the background tmux session has died (meaning nwipe finished)
if ! tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
# Format the output to fit your non-programmer technician layout
# Translates internal R1-C1 to user friendly R1:C1 format
DISPLAY_BAY=$(echo "$BAY" | sed 's/-/:/')
echo -e "${GREEN}[SUCCESS] Drive $DISPLAY_BAY [/dev/$DISK] wiped successfully. PDF certificate generated.${NC}"
# Remove from tracking list so we stop monitoring it
unset DEPLOYED_DRIVES[$DISK]
fi
done
done
echo -e "\n${CYAN}=====================================================${NC}"
echo -e "${GREEN}ALL ACTIVE WIPING TASKS COMPLETED SUCCESSFULLY!${NC}"
echo -e "${CYAN}=====================================================${NC}\n"
echo -e "${YELLOW}Run xfrlogs when ready to transfer logs to USB.${NC}"