diff --git a/umount_kill.sh b/umount_kill.sh index 57778c9..3742fd5 100755 --- a/umount_kill.sh +++ b/umount_kill.sh @@ -1,4 +1,5 @@ #!/bin/bash -e +# vim: set ts=4 sw=4 sts=4 et : # # Written by Jason Mehring (nrgaway@gmail.com) @@ -9,7 +10,7 @@ # # To keep the actual mount mounted, add a '/' to end # -# $1: directory to umount +# ${1}: directory to umount # # Examples: # To kill all processes and mounts within 'chroot-jessie' but keep @@ -25,55 +26,87 @@ . ./functions.sh -# $1 = full path to mount; -# $2 = if set will not umount; only kill processes in mount -umount_kill() { - MOUNTDIR="$1" +mountPoint() { + local mount_point="${1}" # We need absolute paths here so we don't kill everything - if ! [[ "${MOUNTDIR}" = /* ]]; then - MOUNTDIR="${PWD}/${MOUNTDIR}" + if ! [[ "${mount_point}" = /* ]]; then + mount_point="$(readlink -m .)/${mount_point}" fi # Strip any extra trailing slashes ('/') from path if they exist # since we are doing an exact string match on the path - MOUNTDIR=$(echo "${MOUNTDIR}" | sed s#//*#/#g) + echo "$(echo "${mount_point}" | sed s#//*#/#g)" +} + +mountPoints() { + local mount_point="$(mountPoint "${1}")" + echo "$(sudo grep "${mount_point}" /proc/mounts | cut -f2 -d" " | sort -r | grep "^${mount_point}")" +} + +# ${1} = full path to mountpoint; +# ${2} = if set will not umount; only kill processes in mount +umount_kill() { + # Turn off xtrace; but remember its current setting + local xtrace=$(getXtrace) && set +x - # Sync the disk befoe un-mounting to be sure everything is written + local mount_point="$(mountPoint "${1}")" + local kill_only="${2}" + declare -A cache + + # Sync the disk before un-mounting to be sure everything is written sync - warn "-> Attempting to kill any processes still running in '${MOUNTDIR}' before un-mounting" - for dir in $(sudo grep "${MOUNTDIR}" /proc/mounts | cut -f2 -d" " | sort -r | grep "^${MOUNTDIR}") + output "${red}Attempting to kill any processes still running in '${mount_point}' before un-mounting${reset}" + mounts="$(mountPoints "${mount_point}")" + for dir in ${mounts[@]} do - sudo lsof "$dir" 2> /dev/null | \ - grep "$dir" | \ + # Escape filename (convert spaces to '\ ', etc + dir="$(printf "${dir}")" + + # Skip if already in cache + [[ ${cache["${dir}"]+_} ]] && continue || cache["${dir}"]=1 + + # Kill of any processes within mountpoint + sudo lsof "${dir}" 2> /dev/null | \ + grep "${dir}" | \ tail -n +2 | \ awk '{print $2}' | \ xargs --no-run-if-empty sudo kill -9 - if ! [ "$2" ] && $(mountpoint -q "$dir"); then - info "un-mounting $dir" - sudo umount -n "$dir" 2> /dev/null || \ - sudo umount -n -l "$dir" 2> /dev/null || \ - error "umount $dir unsuccessful!" - elif ! [ "$2" ]; then - # Look for (deleted) mountpoints - info "not a regular mount point: $dir" - base=$(basename "$dir") - dir=$(dirname "$dir") - base=$(echo "$base" | sed 's/[\].*$//') - dir="$dir/$base" - sudo umount -v -f -n "$dir" 2> /dev/null || \ - sudo umount -v -f -n -l "$dir" 2> /dev/null || \ - error "umount $dir unsuccessful!" + # Umount + if ! [ "${kill_only}" ]; then + + # Mount point found in mtab + if $(sudo /usr/bin/mountpoint -q "${dir}"); then + info "umount ${dir}" + sudo umount -n "${dir}" 2> /dev/null || \ + sudo umount -n -l "${dir}" 2> /dev/null || \ + error "umount ${dir} unsuccessful!" + + # Umount entries not found within '/usr/bin/mountpoint' + else + # Look for (deleted) mountpoints + info "not a regular mount point: ${dir}" + base="$(basename "${dir}")" + dir="$(dirname "${dir}")" + base="$(echo "${base}" | sed 's/[\].*$//')" + dir="${dir}/${base}" + sudo umount -v -f -n "${dir}" 2> /dev/null || \ + sudo umount -v -f -n -l "${dir}" 2> /dev/null || \ + error "umount ${dir} unsuccessful!" + fi fi done + + # Return xtrace to original state + setXtrace "${xtrace}" } kill_processes_in_mount() { - umount_kill $1 "false" || : + umount_kill ${1} "false" || : } -if [ $(basename "$0") == "umount_kill.sh" -a "$1" ]; then - umount_kill "$1" +if [ $(basename "${0}") == "umount_kill.sh" -a "${1}" ]; then + umount_kill "${1}" fi