Skip to content

Instantly share code, notes, and snippets.

@doublej472
Last active January 4, 2019 18:23
Show Gist options
  • Save doublej472/d5b08f08a6068b6a12f103c278528248 to your computer and use it in GitHub Desktop.
Save doublej472/d5b08f08a6068b6a12f103c278528248 to your computer and use it in GitHub Desktop.
Simple "Secure" disk wiping script
#!/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