#!/usr/bin/env bash # process_check.sh — systemd service liveness. set -euo pipefail SERVICE="${1:-}" if [ -z "$SERVICE" ]; then echo '{"health":"unknown","signalKind":"process-check","evidence":"no service name provided"}' exit 0 fi if ! command -v systemctl >/dev/null 2>&1; then echo '{"health":"unknown","signalKind":"process-check","evidence":"systemctl not found"}' exit 0 fi # `systemctl is-active` PRINTS the state and exits non-zero when the unit is # not active, so `... || echo unknown` appended a second line and produced # "paperless is inactive\nunknown" — a raw newline inside a JSON string, which # the scheduler rejected as invalid output. head -1 keeps the first line and # the fallback only fires when there was no output at all. STATE=$(systemctl is-active "$SERVICE" 2>/dev/null | head -1 || true) [ -z "$STATE" ] && STATE="unknown" # Belt and braces: a unit name or state containing a quote would break the # hand-built JSON below just as thoroughly. STATE=${STATE//\"/} SAFE_SERVICE=${SERVICE//\"/} if [ "$STATE" = "active" ]; then echo "{\"health\":\"healthy\"}" else # signalKind is a taxonomy, not a per-service label. Emitting "$SERVICE" # here minted a distinct signal kind for every service (kind=paperless, # kind=qbit, …), which no approval_rule can match and which makes # "how many process checks are failing?" unanswerable. echo "{\"health\":\"degraded\",\"signalKind\":\"process\",\"evidence\":\"$SAFE_SERVICE is $STATE\"}" fi