hddetach

The hddetach script is a Bash script to safely detach (umount+sync+stop) an external hard disk on a GNU/Linux system.

The only argument $1 must be the label of a volume (partition) in the hard disk (e.g. MYDATA) which is mounted on the file system.
The script gets the device path (e.g. /dev/sdb) of the disk which holds the volume labeled $1 and then try to umount all the disk’s volumes, sync the internal cache and stop the disk and finally to removes it from the system (delete volume icon(s), file manager, desktop etc.).
Superuser rights are requested.

The hddetach script is free software, released under the terms of the GNU General Public License version 3 or (at your option) any later version.

Comments, suggestions and bug reports are welcome.

#!/bin/bash
#
# NAME
# 	hddetach
# 
# SYNOPSIS
# 	hddetach 
# 
# DESCRIPTION
# 	This script safely detach an external hard disk.
# 	The only argument $1 must be the label of one volume (partition) of 
# 	the hard disk (e.g. MYDATA) which is mounted on the file system.
# 	The script gets the device path (e.g. /dev/sdb) of the disk which holds 
# 	the volume labeled $1 and then try to umount all the disk's volumes, sync 
# 	the internal cache and stop the disk and finally to removes it from the 
# 	system (delete volume icon(s), file manager, desktop etc.).
# 	Superuser rights are requested.
# 	
# AUTHOR
# 	Alexus
# 	
# COPYRIGHT
# 	Copyright (c) 2014+ Alexus
# 	License: GPLv3+ (GNU GPL version 3 or later)
# 	This program is free software: you can redistribute it and/or modify
# 	it under the terms of the GNU General Public License as published by
# 	the Free Software Foundation, either version 3 of the License, or
# 	(at your option) any later version.
# 	This program is distributed in the hope that it will be useful,
# 	but WITHOUT ANY WARRANTY; without even the implied warranty of
# 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# 	GNU General Public License for more details.
# 	You should have received a copy of the GNU General Public License
# 	along with this program.  If not, see http://www.gnu.org/licenses/.

# Function desc
desc() {
echo ""
echo "${0##*/}: safely detach an external hard disk"
echo "$COPY, version $VER $DATE"
echo ""
}

# Function usage
usage() {
echo "  Usage: ${0##*/} "
echo "  : label of one volume (partition) of the disk to detach"
press_key
exit 1 
}

# Function press_key
press_key() { echo ""; read -rsn 1 -p "Press any key to exit..."; echo ""; echo "";}

# Function umount_all
umount_all() { local dev="$DEVNAME"; mount | cut -d' ' -f1 | while read vol; do if [[ $vol =~ /dev/$dev. ]]; then umount "$vol"; fi; done; } 

# Intro
VER="1.0"
DATE="18/11/2014"
COPY="Copyright (c) 2014+ Alexus, GPLv3+"
desc

# Check argument
if [[ $# -eq 0 ]]; then echo "  *** Fatal error: Missing argument."; usage; fi

# Get disk device path and device name
LABEL=$1
PATTERN="\[$LABEL\]"
DEVPATH=$(mount -l | grep $PATTERN | cut -d' ' -f1)
DEVNAME=$(echo $DEVPATH | cut -d'/' -f3 | grep -Eo "[[:alpha:]]*")

# Check disk presence
if [[ ${#DEVNAME} -eq 0 ]]; then echo "  *** Fatal error: Not found any device with a volume labeled '$LABEL'."; usage; fi

# Ask user confirmation
echo "  Disk /dev/$DEVNAME holding a volume labeled '$LABEL' will be detached."
echo "  Superuser rights might be requested."
read -p "  Continue? (y/N) " -n 1 -r
if [[ ! "$REPLY" =~ ^[Yy]$ ]]; then echo "  Nothing done."; press_key; exit 0; fi
echo ""

# Unmount partitions on disk
echo "  Trying to umount all the volumes on $DEVPATH..."
umount_all

# Detaches (sync, stop, forget) disk and exit
echo "  Trying to sync, stop and forget $DEVNAME disk..."
sudo sdparm --command=sync /dev/$DEVNAME
sudo sdparm --command=stop /dev/$DEVNAME
sudo sh -c "echo 1 >/sys/block/$DEVNAME/device/delete"
echo "  Done."
press_key
exit 0

Leave a Reply