From 51c6a7b6483a09463b7fc6c1d0441985ef4d6599 Mon Sep 17 00:00:00 2001 From: fds2610-bot Date: Wed, 2 Sep 2026 12:49:34 +0200 Subject: [PATCH] OPs-Agent bleibt in der Praesenz: check_fds.sh meldet working/idle check_fds.sh rief last_seen_at des OPs-Agenten nie an - der Agent fiel zehn Minuten nach seiner Registrierung dauerhaft vom Schreibtisch, obwohl der Ping-Check normal weiterlief. Das Skript meldet jetzt zu Beginn "working" und am Ende (auch bei einem fruehen Abbruch, per trap) "idle" per POST /api/v1/agents/{id}/activity, analog zum Cron-Skript des Entwickler-Agenten. Fehler dabei werden nur protokolliert, nicht fatal. Dafuer braucht monitor-api.conf zusaetzlich MONITOR_AGENT_ID: register-ops-agent.sh schreibt sie bei einer Neuregistrierung mit und traegt sie bei einer bestehenden, aber noch unmigrierten Datei ohne Neuregistrierung nach. Schliesst #75. Co-Authored-By: Claude Sonnet 5 --- README.md | 16 +++++++++++++--- check_fds.sh | 37 +++++++++++++++++++++++++++++++++++++ monitor-api-sample.conf | 6 ++++++ register-ops-agent.sh | 37 ++++++++++++++++++++++++++++++------- 4 files changed, 86 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index b2736d8..7557346 100644 --- a/README.md +++ b/README.md @@ -149,12 +149,16 @@ läuft als die API — dann fällt der Umweg über die Datei `status.txt` weg: ``` Das Skript liest `MONITOR_ADMIN_API_KEY` und `MONITOR_API_BASE` aus der `.env`, legt einen Agenten der Rolle `ops` an (sitzt als „OPs" sichtbar an einem Schreibtisch, Issue #66) und - schreibt den nur einmalig ausgegebenen API-Key mit `chmod 600` nach `monitor-api.conf`. - Eine bestehende `monitor-api.conf` überschreibt es nicht (`--force` erzwingt es). + schreibt den nur einmalig ausgegebenen API-Key mitsamt der Agenten-ID (`MONITOR_AGENT_ID`) + mit `chmod 600` nach `monitor-api.conf`. + Eine bestehende `monitor-api.conf` überschreibt es nicht (`--force` erzwingt es); fehlt dort + nur `MONITOR_AGENT_ID` (ältere Installationen, Issue #75), trägt das Skript die ID ohne + Neuregistrierung nach. Von Hand geht es weiterhin so: Agenten wie in Weg 2 registrieren (Rolle `ops`), `monitor-api-sample.conf` nach `monitor-api.conf` neben `check_fds.sh` kopieren, dort - `MONITOR_API_BASE` (ohne `/api/v1`) und `MONITOR_API_KEY` eintragen, `chmod 600` setzen. + `MONITOR_API_BASE` (ohne `/api/v1`), `MONITOR_API_KEY` und `MONITOR_AGENT_ID` eintragen, + `chmod 600` setzen. `check_fds.sh` meldet dann nach jedem Ping zusätzlich per REST (`online` → `ok`, `offline` → `error`) und schreibt `status.txt` unverändert weiter für den alten Wandmonitor. @@ -162,6 +166,12 @@ Die System-ID entsteht dabei aus dem Hostnamen (`Nextcloud(intern)` → `nextclo der Originalname bleibt als Anzeigename erhalten. Ist die API nicht erreichbar, läuft die Ping-Überwachung normal weiter und protokolliert nur eine Warnung. +Zusätzlich meldet `check_fds.sh` bei jedem Lauf `working` zu Beginn und `idle` am Ende +(`POST /api/v1/agents/{id}/activity`, benötigt `MONITOR_AGENT_ID`) — ohne diese Meldung fiel +der OPs-Agent zehn Minuten nach der Registrierung dauerhaft aus der Präsenz, obwohl der +Ping-Check längst lief (Issue #75). Fehlt `MONITOR_AGENT_ID`, bleibt nur diese Meldung aus, +der Rest von `check_fds.sh` läuft unverändert weiter. + ## ⚙️ Hosts über die Oberfläche pflegen Ist Weg 3 eingerichtet, muss für einen neuen oder entfernten Server niemand mehr die diff --git a/check_fds.sh b/check_fds.sh index e08b3ab..beb57ed 100755 --- a/check_fds.sh +++ b/check_fds.sh @@ -20,6 +20,7 @@ API_CONF="$SCRIPT_DIR/monitor-api.conf" # eine lokale Datei und erreicht die API dann nicht. MONITOR_API_BASE="" MONITOR_API_KEY="" +MONITOR_AGENT_ID="" if [ -f "$API_CONF" ]; then # shellcheck source=/dev/null . "$API_CONF" @@ -140,6 +141,34 @@ report_to_api() { fi } +# Meldet den eigenen Zustand per POST /api/v1/agents/{id}/activity (Issue #75): ohne diese +# Meldung faellt der OPs-Agent zehn Minuten nach seiner Registrierung aus der Praesenz +# (AgentRepository::PRESENCE_TIMEOUT_SECONDS), obwohl der Ping-Check laengst laeuft - bisher +# schrieb kein Aufruf in check_fds.sh je last_seen_at. MONITOR_AGENT_ID fehlt in aelteren +# monitor-api.conf; ist es leer, meldet die Funktion wie report_to_api still nichts, statt +# den Lauf abzubrechen. +report_activity() { + local state="$1" + + if [ -z "$MONITOR_API_BASE" ] || [ -z "$MONITOR_API_KEY" ] || [ -z "$MONITOR_AGENT_ID" ]; then + return 0 + fi + + local code + if ! code=$(curl -s -o /dev/null -w '%{http_code}' --max-time 10 \ + -X POST "${MONITOR_API_BASE%/}/api/v1/agents/$MONITOR_AGENT_ID/activity" \ + -H "Content-Type: application/json" \ + -H "X-Api-Key: ${MONITOR_API_KEY}" \ + -d "{\"state\":\"$(json_escape "$state")\"}"); then + echo " Warnung: API unter $MONITOR_API_BASE nicht erreichbar, Zustand '$state' nicht gemeldet." + return 0 + fi + + if [ "$code" != "200" ]; then + echo " Warnung: API antwortet mit HTTP $code auf die Zustandsmeldung '$state'." + fi +} + # Funktion zum Prüfen einer IP und Schreiben des Status check_ip() { local hostname="$1" @@ -187,6 +216,14 @@ check_ip() { # Hauptskript echo "Pruefung: $(date)" + +# Rahmt den ganzen Lauf, damit der Agent auch bei einem fruehen "exit 1" (fehlende +# hosts.conf/mail_fds.py weiter unten) nicht dauerhaft als "working" haengen bleibt - +# analog zum Cron-Skript des Entwickler-Agenten, das ebenfalls working/idle um seinen Lauf +# herum meldet (Issue #75). +trap 'report_activity idle' EXIT +report_activity working + sync_hosts_from_api if [ ! -f "$HOST_FILE" ]; then echo "Fehler: Datei $HOST_FILE nicht gefunden." diff --git a/monitor-api-sample.conf b/monitor-api-sample.conf index 1a602f7..fc4bed4 100644 --- a/monitor-api-sample.conf +++ b/monitor-api-sample.conf @@ -19,3 +19,9 @@ MONITOR_API_BASE="http://monitor.example.lan:8091" # API-Key des registrierten Agenten MONITOR_API_KEY="" + +# ID des registrierten Agenten (aus der Registrierungsantwort). Noetig, damit check_fds.sh +# per POST /api/v1/agents/{id}/activity working/idle melden und so in der Praesenz bleiben +# kann (Issue #75) - ohne diesen Wert unterbleibt nur diese Meldung, alles andere +# funktioniert weiter wie zuvor. +MONITOR_AGENT_ID="" diff --git a/register-ops-agent.sh b/register-ops-agent.sh index 1cac5b1..78f7904 100755 --- a/register-ops-agent.sh +++ b/register-ops-agent.sh @@ -61,23 +61,45 @@ if [ "$ADMIN_API_KEY" = "change-me" ]; then echo "Fehler: MONITOR_ADMIN_API_KEY ist noch der Beispielwert 'change-me'." >&2 exit 1 fi -if [ -e "$API_CONF" ] && [ "$FORCE" -ne 1 ]; then - echo "Fehler: $API_CONF existiert bereits - der bisherige OPs-Agent ist offenbar schon" >&2 - echo " registriert. Zum Neuanlegen die Datei wegsichern oder --force angeben." >&2 - exit 1 -fi - json_escape() { printf '%s' "$1" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' } # Ein zweiter Agent gleichen Namens wuerde einen weiteren der acht Schreibtische belegen. # GET /api/v1/agents ist unauthentifiziert (API.md "Agenten") und dient hier auch als -# Erreichbarkeitspruefung. +# Erreichbarkeitspruefung. Wird vor der Existenzpruefung von $API_CONF geholt, weil eine +# bestehende, aber noch unmigrierte Datei (Issue #75, siehe unten) die ID aus genau dieser +# Antwort nachtraegt, statt den Agenten neu zu registrieren. agents_json=$(curl -sS --max-time 10 "$API_ROOT/api/v1/agents" 2>/dev/null) || { echo "Fehler: API unter $API_ROOT nicht erreichbar. Laeuft 'docker compose up'?" >&2 exit 1 } + +if [ -e "$API_CONF" ] && [ "$FORCE" -ne 1 ]; then + if ! grep -q '^MONITOR_AGENT_ID=' "$API_CONF"; then + # Migration (Issue #75): aeltere monitor-api.conf kennen MONITOR_AGENT_ID noch nicht, + # ohne das check_fds.sh den Aktivitaets-Endpoint nicht adressieren kann. Die ID laesst + # sich hier ohne Neuregistrierung nachtragen - GET /api/v1/agents kennt sie bereits + # (Reihenfolge der Felder wie von AgentRepository::hidingKey() geliefert: "id" direkt + # vor "display_name"). + # "|| true" haengt am Ende der Pipeline: findet keiner der beiden grep-Aufrufe eine + # Uebereinstimmung, wuerde ihr Exit-Code mit "set -o pipefail" sonst das ganze Skript + # kommentarlos beenden, statt in die Fehlermeldung darunter zu fallen. + existing_id=$(printf '%s' "$agents_json" \ + | grep -oE "\"id\":[0-9]+,\"display_name\":\"$(json_escape "$DISPLAY_NAME")\"" \ + | head -n1 | grep -oE '[0-9]+' || true) + if [ -n "$existing_id" ]; then + printf 'MONITOR_AGENT_ID="%s"\n' "$existing_id" >> "$API_CONF" + echo "MONITOR_AGENT_ID fehlte in $API_CONF und wurde nachgetragen (ID $existing_id)." + exit 0 + fi + fi + + echo "Fehler: $API_CONF existiert bereits - der bisherige OPs-Agent ist offenbar schon" >&2 + echo " registriert. Zum Neuanlegen die Datei wegsichern oder --force angeben." >&2 + exit 1 +fi + if printf '%s' "$agents_json" | grep -q "\"display_name\":\"$(json_escape "$DISPLAY_NAME")\""; then echo "Fehler: Ein Agent namens \"$DISPLAY_NAME\" ist bereits registriert." >&2 echo " Anderen Anzeigenamen uebergeben oder den alten Agenten loeschen." >&2 @@ -117,6 +139,7 @@ cat > "$API_CONF" <