Skip to content
Snippets Groups Projects
check_systemdunit 3.82 KiB
#!/bin/bash
# ================================================================================
#
# CHECK A SINGLE SYSTEMD SERVICE
#
# -------------------------------------------------------------------------------
# 2023-09-05  v1.0  <axel.hahn@unibe.ch>
# 2020-09-06  v1.1  <axel.hahn@unibe.ch>  add params -s, -l
# 2020-09-06  v1.2  <axel.hahn@unibe.ch>  add param -r to use a regex
# 2020-09-18  v1.3  <axel.hahn@unibe.ch>  fix: list units --all to show all stopped units
# 2020-09-18  v1.4  <axel.hahn@unibe.ch>  replace pipes in systemctl status output
# 2020-10-20  v1.5  <axel.hahn@unibe.ch>  remove special chars from systemd status
# ================================================================================

. $( dirname $0 )/inc_pluginfunctions

export self_APPVERSION=1.5

# ----------------------------------------------------------------------
# FUNCTIONS
# ----------------------------------------------------------------------

# show help text
function showHelp(){
    local _self; _self=$(basename $0)
cat <<EOF
$( ph.showImlHelpHeader )

Check a unit using systemctl status.

The status is unknown if the command systemctl is not found.
The status is critical if the service does not exist or is not running.

SYNTAX:
  $_self [-h|-l|-s|-r] UNIT

OPTIONS:

  -h     this help
  -l     list all units
  -s     list service units
  -r     handle UNIT as a regex and search for a single unit. A uniq regex
         is needed to match a single unit. The initial idea was to match a
         servie that has different service names on differen os eg.
         - apache2 vs httpd
         - mysld vs mariadb

  UNIT   Name of a unit - see output of 'systemctl' 

EXAMPLES:

  $_self -s
         list all existing services. For a unit check you need to add the name
         in the 1st column.

  $_self nginx.service
         show status of nginx webservice

  $_self -r "(apache2|httpd)\.service"
         Detect name of Apache httpd service by given regex and show status
         of the found service name

EOF
}

# get the list of units
function _getUnits(){
  systemctl --no-legend --no-pager --all
}

# ----------------------------------------------------------------------
# MAIN
# ----------------------------------------------------------------------

ph.hasParamoption "h" "$@"; bOptHelp=$?

if [ $bOptHelp -eq 0 -o $# -eq 0 ]; then
    showHelp
    exit 0
fi

ph.require "systemctl"

# --- list all units
if ph.hasParamoption "l" "$@" ; then
  echo "List of all systemd units:"
  echo
  _list=$( _getUnits )
  for mytype in $( awk '{ print $1 }' <<< "$_list" | rev| cut -f 1 -d '.' | rev | grep -v '[^a-z]' | sort -u )
  do
    echo "---------- $mytype"
    grep "\.${mytype}" <<< "$_list"
    echo
  done
  exit 0
fi

# --- list service units
if ph.hasParamoption "s" "$@" ; then
  echo "List of service units:"
  echo
  systemctl --no-legend --no-pager --type service
  exit 0
fi

# --- find a service by regex
if ph.hasParamoption "r" "$@" ; then
  _regex="${2}"
  _list=$( _getUnits | awk '{ print $1 }' | sort )
  _unit=$( grep -E "$_regex" <<< "$_list" )

  if [ -z "$_unit" ]; then
    ph.setStatus critical
    ph.status "REGEX '$_regex' does not match any existing unit"
    ph.exit
  fi
  
  if [ $( wc -l <<< "$_unit" ) != "1" ]; then
    ph.setStatus critical
    ph.status "REGEX '$_regex' matches on multiple units on this system:"
    echo "$_unit" | nl
    echo "You need to use a uniq regex."
    ph.exit
  fi
else
  _unit="${1}"
fi

# --- check given unit

_data=$( systemctl --no-pager -l status "${_unit}" 2>&1 | tr '|' ':' )

_status=$( echo "$_data" | head -1 | sed "s#^[^a-zA-Z]*##g" )
if ! grep "Active: active (running) " <<< "${_data}" >/dev/null; then
    ph.setStatus critical
fi
ph.status "${_status}"

echo "$_data" | sed -n "2,\$p" | tr -d '└├' | tr '─' '-'

ph.exit

# ----------------------------------------------------------------------