#!/usr/bin/env bash working_dir="$(dirname $(realpath $0))" # ------------- # - Some Variables # ------------- LOCK_DIR="/tmp/$(basename $0).LOCK" KILL_SIGNAL=HUP CHECK_COMMANDS="$*" # ------------- # - Some functions # ------------- usage() { [[ -n "$1" ]] && error "$1" [[ $terminal ]] && echo -e " \033[1mUsage:\033[m $(basename $0) COMMAND [COMMAND] .. \033[1mDescription\033[m Searches for zombie (defunct) child prozesses from given command(s). If such processes exists, the script tries to kill them by sending a HUP signal to the parent process. At least one command as a cammand line option must be gicen. \033[1mExample:\033[m Search for (and delete) defunct child prozesses of parent '/usr/local/php/bin/php-cgi' $(basename $0) /usr/local/php/bin/php-cgi Search for (and delete) defunct child prozesses of parent processes '/usr/local/sympa/bin/sympa_msg.pl' and '/usr/local/sympa/bin/bulk.pl' $(basename $0) /usr/local/sympa/bin/sympa_msg.pl /usr/local/sympa/bin/bulk.pl " 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 # - Print help? # - if [[ "$(trim $*)" = "-h" ]] || [[ "$(trim $*)" = "--help" ]] ; then usage 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 if [[ -z "$CHECK_COMMANDS" ]]; then usage "At least one command must be given." else for _COMMAND in ${CHECK_COMMANDS[@]} ; do if [[ ! -x "$_COMMAND" ]]; then fatal "no binary/script '$_COMMAND' found on the server" fi done 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 # ------------- # Checking .. # ------------- if $terminal ; then echo "" echo -e " \033[1mCheck for zombie (defunct) child prozesses\033[m" echo " ==========================================" fi for _COMMAND in ${CHECK_COMMANDS[@]} ; do if $(ps -Ao"stat,command" | grep "$(basename ${_COMMAND})" | grep -v grep | grep -e '^[zZ]' > /dev/null 2>&1) then warn "Found Zombie Processes '${_COMMAND}' on '$(hostname -f)':" ps -Ao"stat,user,pid,ppid,command" | grep "$(basename ${_COMMAND})" | 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' .." # - Sending the kill signal # - ps -Ao"stat,pid,ppid,command" | grep "$(basename ${_COMMAND})" | grep -v grep | grep -e '^[zZ]' \ | awk '{ print $3 }' | sort -u | xargs --no-run-if-empty kill -$KILL_SIGNAL if [[ "$?" -eq 0 ]];then sleep 10 ok "Cleaning up zombie processes '${_COMMAND}' seems succsessfully finisched" 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 '${_COMMAND}' failed!" fi else info_terminal "No zombie prossses '${_COMMAND}' found." fi done if $terminal ; then echo "" fi clean_up 0