#!/bin/bash
# vexor_check_systemd_mem — Nagios/NRPE plugin.
#
# Reports a systemd unit's current memory usage (systemctl show -p
# MemoryCurrent) with optional WARNING/CRITICAL thresholds in MB. Works
# for any unit name, including templated units (e.g. nginx.service,
# prosrv@solen.service).
#
# Usage:
#   vexor_check_systemd_mem -u <unit> [-w <warn_MB>] [-c <crit_MB>]
#   vexor_check_systemd_mem <unit> [<warn_MB>] [<crit_MB>]
#
# Exit:
#   0 OK / 1 WARNING / 2 CRITICAL based on memory vs thresholds.
#   3 UNKNOWN if the unit is not found or systemctl is unavailable.
#   An inactive unit reports memory 0 (OK unless a threshold is 0).
#
# Perfdata: memory=<bytes>B;<warn_bytes>;<crit_bytes>;0
set -u

# NRPE often runs plugins with a minimal PATH; make sure systemctl is found.
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:${PATH:-}"

UNIT=""; WARN=""; CRIT=""
POS=0

is_uint() { case "${1:-}" in ''|*[!0-9]*) return 1;; *) return 0;; esac; }

# Accept a value for an option only when it's present and not another flag.
takeval() { # $1 = next token
    if [ -n "${1:-}" ] && [ "${1#-}" = "${1}" ]; then printf '%s' "$1"; return 0; fi
    return 1
}

while [ $# -gt 0 ]; do
    case "$1" in
        -u|--unit)     if v=$(takeval "${2:-}"); then UNIT="$v"; shift 2; else shift 1; fi ;;
        -w|--warning)  if v=$(takeval "${2:-}"); then WARN="$v"; shift 2; else shift 1; fi ;;
        -c|--critical) if v=$(takeval "${2:-}"); then CRIT="$v"; shift 2; else shift 1; fi ;;
        -h|--help)
            echo "usage: $(basename "$0") -u <unit> [-w <warn_MB>] [-c <crit_MB>]"; exit 3 ;;
        *)
            POS=$((POS+1))
            case "$POS" in
                1) [ -z "$UNIT" ] && UNIT="$1" ;;
                2) [ -z "$WARN" ] && WARN="$1" ;;
                3) [ -z "$CRIT" ] && CRIT="$1" ;;
            esac
            shift 1 ;;
    esac
done

# Empty / non-numeric thresholds mean "no threshold".
is_uint "$WARN" || WARN=""
is_uint "$CRIT" || CRIT=""

if [ -z "$UNIT" ]; then
    echo "UNKNOWN: usage: $(basename "$0") -u <unit> [-w <warn_MB>] [-c <crit_MB>]"
    exit 3
fi

SYSTEMCTL=""
for c in systemctl /usr/bin/systemctl /bin/systemctl /usr/sbin/systemctl /sbin/systemctl; do
    if command -v "$c" >/dev/null 2>&1; then SYSTEMCTL=$(command -v "$c"); break
    elif [ -x "$c" ]; then SYSTEMCTL="$c"; break; fi
done
if [ -z "$SYSTEMCTL" ]; then
    echo "UNKNOWN: systemctl not found (no systemd, or restricted PATH)"; exit 3
fi

LOAD=$("$SYSTEMCTL" show -p LoadState --value "$UNIT" 2>/dev/null)
if [ "$LOAD" = "not-found" ] || [ -z "$LOAD" ]; then
    echo "UNKNOWN: unit $UNIT not found on this host"; exit 3
fi

STATE=$("$SYSTEMCTL" is-active "$UNIT" 2>/dev/null | head -n1)
MEM=$("$SYSTEMCTL" show -p MemoryCurrent --value "$UNIT" 2>/dev/null)
case "$MEM" in
    ''|'[not set]'|infinity|*[!0-9]*) MEM=0 ;;
esac

MB=$(( MEM / 1048576 ))

warn_b=""; crit_b=""
[ -n "$WARN" ] && warn_b=$(( WARN * 1048576 ))
[ -n "$CRIT" ] && crit_b=$(( CRIT * 1048576 ))

PERF="memory=${MEM}B;${warn_b};${crit_b};0"

EC=0; SEV="OK"
if [ -n "$crit_b" ] && [ "$MEM" -ge "$crit_b" ]; then
    EC=2; SEV="CRITICAL"
elif [ -n "$warn_b" ] && [ "$MEM" -ge "$warn_b" ]; then
    EC=1; SEV="WARNING"
fi

printf '%s: %s memory %sMB (state=%s) | %s\n' "$SEV" "$UNIT" "$MB" "$STATE" "$PERF"
exit "$EC"
