Last active
January 4, 2019 18:23
-
-
Save doublej472/d5b08f08a6068b6a12f103c278528248 to your computer and use it in GitHub Desktop.
Simple "Secure" disk wiping script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Simple "Secure" block device wiping script | |
# Author: Jonathan Frederick (doublej472) | |
# Usage: | |
# wipe.sh [block devices] | |
# Description: | |
# A simple block device wiper, supports wiping block devices in parallel, | |
# configuring the number of passes, configuring the data source, and progress reporting | |
# | |
# Most suitable for wiping hard drives, created as an alternative to DBAN. | |
# This is most useful when run from an external device, live environment, or loaded in RAM | |
# Such as a Gentoo or Arch Linux install environment | |
# | |
# By default it will wipe the specified block devices with 3 passes using data from /dev/urandom | |
# USER CONFIGURABLE SECTION | |
# Number of times to write data to block device | |
PASSES=3 | |
# Source of data to write to block device | |
RNG_SRC='/dev/urandom' | |
# Frequency of progress reports in seconds | |
REPORT_FREQ=10 | |
# END USER CONFIGURATION | |
# Setup main thread signal handler | |
trap 'on_term' EXIT | |
# Print usage and exit | |
usage() { | |
echo "Usage: $0 [block devices]" | |
exit 1 | |
} | |
# Main termination signal handler | |
# Simply wait for children to finish, then exit | |
on_term() { | |
wait | |
exit 1 | |
} | |
# Thread termination signal handler | |
# Kills process at $pid ( which is specified to be the dd command executed in | |
# wipe_disk() ), then exit | |
on_thread_term() { | |
# pid is defined to be the dd process | |
echo "Killing $pid" | |
kill -s SIGTERM $pid | |
exit 1 | |
} | |
# Prints current progress of disk wipe | |
# Variables are defined in wipe_disk() | |
thread_print_status() { | |
echo "Block device $disk, Pass $i" | |
kill -s SIGUSR1 $pid | |
} | |
# Wipe the specified block device | |
# Called as a background process | |
wipe_disk() { | |
disk=$1 | |
# Register thread exit signal handler | |
trap 'on_thread_term' EXIT | |
# Also handle SIGUSR1, for printing status | |
trap 'thread_print_status' USR1 | |
for i in $(seq 1 $PASSES); do | |
echo "Starting wipe on $disk pass $i" | |
# Launch dd command in background and store pid | |
dd if=/dev/urandom of=$disk bs=4M & | |
pid=$! | |
# Wait for dd to finish, or until SIGUSR1 is caught | |
# Need to handle wait returning a value greater than | |
# 128, which means a signal was handled, and we need to | |
# restart the wait | |
wait | |
while [ $? -gt 128 ]; do | |
wait | |
done | |
done | |
echo "Wiping $disk finished" | |
} | |
# Print usage if -h or --help is specified, or no flags are passed | |
if [ $# -eq 0 ] | |
then | |
usage | |
else | |
for arg in $@; do | |
if [ $arg = '--help' ] || [ $arg = '-h' ]; then | |
usage | |
fi | |
done | |
fi | |
# Ensure we are wiping block devices | |
for d in $@; do | |
if ! [ -b $d ] | |
then | |
echo "$d is not a block device!" | |
exit 1 | |
fi | |
done | |
# From this point forwards, we can be sure that $@ is a list | |
# of block devices | |
# Prompt user for confirmation | |
for d in $@; do | |
echo $d | |
done | |
echo "These block devices will be wiped, proceed? (y/N)" | |
read RESPONSE | |
if [ -z $RESPONSE ] || [ $RESPONSE != 'y' ] | |
then | |
echo "Stopping." | |
exit 0 | |
fi | |
# List of PIDs for bash subroutines | |
pids='' | |
# Launch disk wiping subroutines | |
for d in $@; do | |
wipe_disk $d & | |
pids="$pids $!" | |
sleep 0.05 | |
done | |
# Wait for subroutines to finish | |
# We count the running child processes (bash subroutines), if they are still running | |
# then ask them to print their status. Otherwise, skip over it. | |
# If no processes are running, then exit program. | |
# Put in fake running value before we begin | |
running=1 | |
while [ $running -gt 0 ]; do | |
# Assume that no subroutines are running until proven otherwise | |
running=0 | |
for p in $pids; do | |
# kill with signal 0, which only checks if the PID is valid and running | |
if $(kill -s 0 $p); then | |
running=$((running+1)) | |
kill -s SIGUSR1 $p | |
sleep 1 | |
fi | |
done | |
sleep $REPORT_FREQ | |
done | |
echo "Done." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment