diff --git a/.gitignore b/.gitignore index 251f61e..a3b58e5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -*.swl +*.swp /conf/*.conf /BAK/* diff --git a/clean_up_from_zombies.sh b/remove_zombies_command.sh similarity index 100% rename from clean_up_from_zombies.sh rename to remove_zombies_command.sh diff --git a/remove_zombies_user.sh b/remove_zombies_user.sh new file mode 100755 index 0000000..37ab892 --- /dev/null +++ b/remove_zombies_user.sh @@ -0,0 +1,265 @@ +#!/usr/bin/env bash + +working_dir="$(dirname $(realpath $0))" + +# ------------- +# - Some Variables +# ------------- + +LOCK_DIR="/tmp/$(basename $0).LOCK" + +KILL_SIGNAL=HUP + +#CHECK_USER="$*" + + +# ------------- +# - Some functions +# ------------- + +usage() { + + + [[ -n "$1" ]] && error "$1" + + + [[ $terminal ]] && echo -e " +\033[1mUsage:\033[m + + $(basename $0) -u + +\033[1mDescription\033[m + + Searches for zombie (defunct) child prozesses owned by a given user. If such + processes exists, the script tries to kill them by sending a HUP signal to + the parent process. + + A user must be given using option '-u'. + +\033[1mOptions\033[m + + -h + Prints this help. + + -u + Searches for zombie (defunct) prozesses owned by this user. + +\033[1mExample:\033[m + + Search for (and delete) defunct child prozesses owned by user 'sympa'' + + $(basename $0) -u sympa + +" + + clean_up 1 + +} + +clean_up() { + + # Perform program exit housekeeping + rm -rf "$LOCK_DIR" + exit $1 +} + +trim() { + local var="$*" + var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters + var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters + echo -n "$var" +} + +fatal(){ + echo "" + if $terminal ; then + echo -e " [ \033[31m\033[1mFatal\033[m ]: $*" + echo "" + echo -e " \033[31m\033[1mScript was interupted\033[m!" + else + echo "[ Fatal ]: $*" + echo "" + echo " Script was terminated...." + fi + echo "" + clean_up 1 +} + +error (){ + echo "" + if $terminal ; then + echo -e " [ \033[31m\033[1mError\033[m ]: $*" + else + echo "[ Error ]: $*" + fi + echo "" +} + +warn (){ + echo "" + if $terminal ; then + echo -e " [ \033[33m\033[1mWarning\033[m ]: $*" + else + echo "[ Warning ]: $*" + fi + echo "" +} + +info (){ + echo "" + if $terminal ; then + echo -e " [ \033[32m\033[1mInfo\033[m ]: $*" + else + echo "[ Info ]: $*" + fi + echo "" +} +info_terminal (){ + if $terminal ; then + echo "" + echo -e " [ \033[32m\033[1mInfo\033[m ]: $*" + echo "" + fi +} + +ok (){ + echo "" + if $terminal ; then + echo -e " [ \033[32m\033[1mOk\033[m ]: $*" + else + echo "[ Ok ]: $*" + fi + echo "" +} + + +# ------------- +# - Check some prerequisites +# ------------- + +# - Is this script running on terminal ? +# - +if [[ -t 1 ]] ; then + terminal=true +else + terminal=false +fi + +if [[ -z "$(which basename)" ]]; then + fatal 'It seems "basename" is not installed, but needed!' +fi + +if [[ -z "$(which realpath)" ]]; then + fatal 'It seems "realpath" is not installed, but needed!' +fi + + + +# ------------- +# - Jobhandling +# ------------- + +# - If job already runs, stop execution.. +# - +if mkdir "$LOCK_DIR" 2> /dev/null ; then + + ## - Remove lockdir when the script finishes, or when it receives a signal + trap clean_up SIGHUP SIGINT SIGTERM + +else + + datum="$(date +"%d.%m.%Y %H:%M")" + + fatal "A previos instance of that script \"$(basename $0)\" seems already be running." + + exit 1 + +fi + + +# ------------- +# - Read Commanline Arguments +# ------------- + +while getopts hu: opt ; do + case $opt in + h) usage ;; + u) CHECK_USER=$OPTARG ;; + *) usage + esac +done + +if [[ -z "$CHECK_USER" ]]; then + usage "No user (option -u) given" +fi + +shift $(expr $OPTIND - 1) +[[ "$#" -gt 0 ]] && usage "Wrong number of arguments given!" + + +# ------------- +# Checking .. +# ------------- + +if $terminal ; then + echo "" + echo -e " \033[1mCheck for zombie (defunct) child prozesses owned by a given user\033[m" + echo " ================================================================" +fi + + +if $(ps -Ao"stat,user,command" | grep "${CHECK_USER}" | grep -v grep | grep -e '^[zZ]' > /dev/null 2>&1) +then + + warn "Found Zombie Processes '${CHECK_USER}' on '$(hostname -f)':" + + # - Print out the concerning lines frp 'ps' output. + # - + ps -Ao"stat,user,pid,ppid,command" | grep "$(basename ${CHECK_USER})" | grep -v grep | grep -e '^[zZ]' + + membefore=$(cat /proc/meminfo | grep Committed_AS | awk '{print $2}') + + info "Trying a graceful kill to the concerning parents with signal '$KILL_SIGNAL' .." + + # - Process ID(s) of the zombie process(es) + # - + ZOMBIE_PIDS="$(ps -Ao"stat,user,pid,ppid,command" | grep "${CHECK_USER}" | grep -v grep | grep -e '^[zZ]' \ + | awk '{ print $3 }' | sort -u)" + + # - Sending the kill signal ($KILL_SIGNAL) to the parent process ID(s) + # - + ps -Ao"stat,user,pid,ppid,command" | grep "${CHECK_USER}" | grep -v grep | grep -e '^[zZ]' \ + | awk '{ print $4 }' | sort -u | xargs --no-run-if-empty kill -$KILL_SIGNAL + + if [[ "$?" -eq 0 ]];then + + declare -i count=1 + for _PID in $ZOMBIE_PIDS ; do + if [[ $count -eq 1 ]]; then + KILLED_PIDS="$_PID" + else + KILLED_PIDS="$KILLED_PIDS $_PID" + fi + ((count++)) + done + + sleep 10 + + ok "Cleaning up zombie processes owned by user '${CHECK_USER}' seems succsessfully finisched" + + ok "$count zombie process(es) with PID(s) '${KILLED_PIDS}' removed from process list" + + memafter=`cat /proc/meminfo | grep Committed_AS | awk '{print $2}'` + + info "`expr $membefore - $memafter` KB RAM has been freed" + else + error "Cleaning up zombie processes owned by user '${CHECK_USER}' failed!" + fi +else + info_terminal "No zombie prossses owned by user '${CHECK_USER}' found." +fi + +if $terminal ; then + echo "" +fi +clean_up 0