saving files
This commit is contained in:
Executable
+80
@@ -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
@@ -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 "==================================="
|
||||
'')
|
||||
@@ -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
@@ -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 "$@"
|
||||
@@ -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 "$@"
|
||||
@@ -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}"
|
||||
Reference in New Issue
Block a user