Skip to content
Snippets Groups Projects
Select Git revision
  • ea77a07ef9772fe21a6fbba609d5fea26c58c9d6
  • master default protected
2 results

checkservices

Blame
  • checkservices 3.72 KiB
    #!/bin/bash
    
    # Copyright © Sébastien Luttringer
    #
    # 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 2
    # 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, write to the Free Software
    # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    
    # Check running systemd services for binary update
    # Convenient way to restart updated systemd service after upgrade
    
    # disable grep options to avoid non default behaviour
    unset GREP_OPTIONS
    
    # Systemd cgroup path
    systemd_cgroup_base_path='/sys/fs/cgroup/systemd'
    
    (( $UID != 0 )) && echo 'You need to be root' && exit 1
    
    if [[ -t 1 ]]; then
    	shopt -s xpg_echo
    	c_title='\e[1;33m'
    	c_svc='\e[1;31m'
    	c_rst='\e[m'
    fi
    
    usage() {
    	echo "usage ${0##*/} [options]"
    	echo 'options:'
    	echo '   -h: this help' >&2
    	echo '   -r: restart services' >&2
    	echo '   -R: reload services' >&2
    	echo "   -s: serialize action" >&2
    	echo "   -n: don't call systemd daemon-reload" >&2
    	echo "   -N: don't display status of restart/reload units" >&2
    	echo "   -u: list service in users slice" >&2
    	echo "   -v: verbose mode" >&2
    	exit 1
    }
    
    while getopts 'hrRsnNuv' opt; do
    	case $opt in
    		r) systemd_cmd='restart';;
    		R) systemd_cmd='reload';;
    		s) serial=true;;
    		n) no_reload=1;;
    		N) no_status=1;;
    		l) list=true;;
    		u) user_slice=true;;
    		v) verbose=true;;
    		*) usage;;
    	esac
    done
    shift $((OPTIND - 1));
    (( $# > 0 )) && usage
    
    # avoid to be sighup'ed by interactive shell
    trap '' SIGHUP
    
    # reload units list
    [[ -z $no_reload ]] && systemctl --system daemon-reload
    
    # list of running services
    # don't use systemctl -s because require v206 of systemd. too young at the moment.
    declare -a services
    services=($(systemctl --no-legend --full -t service|grep running|sed -rn 's/^(.*\.service).*/\1/p'))
    
    # beggar count
    declare -a needy=() pids=()
    declare -i pid=0
    
    for svc in "${services[@]}"; do
    	unit_path=$(systemctl -p ControlGroup show "$svc"|cut -f 2 -d=)
    	# check if unit is in system slice
    	[[ "$unit_path" =~ /user\.slice/ && ! "$user_slice" == true ]] && continue
    	pids=( $(< "$systemd_cgroup_base_path/$unit_path/tasks") )
    	if (( "${#pids[*]}" == 0 )); then
    		echo "** Unable to get pid of $svc" >&2
    		continue
    	fi
    	deleted=''
    	for pid in "${pids[@]}"; do
    		deleted=$(grep '(deleted)' "/proc/$pid/maps"|sed -nr 's|^\S+ ..x. \S+ \S+ \S+ \s+||p'|sort|uniq)
    		if [[ -n $deleted ]]; then
    			needy+=("$svc")
    			if [[ $verbose ]]; then
    				echo "${c_title}Service:${c_svc} $svc${c_rst}"
    				echo "${c_title}Pid:${c_rst} $pid"
    				echo "${c_title}Commands:${c_rst}"
    				echo "systemctl reload '$svc'"
    				echo "systemctl restart '$svc'"
    				echo "${c_title}Deleted files:${c_rst}"
    				echo "$deleted"
    				echo
    			else
    				echo "systemctl restart '$svc'"
    			fi
    			if [[ $systemd_cmd ]]; then
    				systemctl "$systemd_cmd" "$svc" &
    				# wait process to terminate when serialize
    				[[ -n $serial ]] && wait
    				# display status directly when not serialize
    				[[ -n $serial && -z $no_status ]] && systemctl --lines=0 status "$svc"
    			fi
    			break
    		fi
    	done
    done
    wait
    
    # show units status
    if [[ -z $serial && -z $no_status && $systemd_cmd && ${needy[*]} ]]; then
    	systemctl --lines=0 status "${needy[@]}"
    fi
    
    if [[ $verbose ]]; then
    	systemctl --failed --all --no-pager --full list-units
    else
    	systemctl --failed --all --no-pager --no-legend --full list-units
    fi
    
    exit 0