Einfaches Server-Monitoring mit Bordmitteln einrichten
Ein Prüfskript, ein systemd-Timer und ein getesteter Benachrichtigungsweg reichen für einen einzelnen Root Server. Diese Anleitung zeigt, was zu überwachen ist, wie Sie jeden Schritt nachprüfen und ab wann sich der große Werkzeugkasten lohnt.
Ein Server meldet sich nicht von selbst, wenn etwas schiefgeht. Er läuft weiter, bis er nicht mehr weiterläuft, und die erste Rückmeldung kommt von einem Kunden oder von Ihnen, wenn Sie zufällig hinsehen. Diese Anleitung baut die kleinste Überwachung, die das beendet: ein Prüfskript, ein systemd-Timer, ein Benachrichtigungsweg. Keine Zeitreihendatenbank, kein Dashboard, kein zusätzlicher offener Port.
Bezugssysteme sind Debian 13 (trixie), Debian 12 (bookworm), Ubuntu 24.04 LTS und Ubuntu 22.04 LTS. Wo sich die vier unterscheiden, steht es ausdrücklich dabei. Alle Befehle sind für den Betrieb als root geschrieben; als normaler Benutzer stellen Sie jedem Befehl ein sudo voran. Diese Anleitung vertieft Schritt 8 der Checkliste für einen neuen Rootserver.
Was Sie überhaupt überwachen sollten
Der häufigste Fehler beim ersten Monitoring ist nicht, zu wenig zu messen, sondern zu viel. Wer 40 Kennzahlen sammelt, sieht keine davon an. Sinnvoll ist nur, was den Betrieb beenden kann und worauf Sie reagieren können. Es bleiben sieben Punkte.
| Kennzahl | Warum sie auf die Liste gehört | Woher der Wert kommt | Sinnvolle Schwelle |
|---|---|---|---|
| Plattenplatz | Häufigste Ausfallursache, die niemand kommen sieht | df --output=pcent,target | ab 85 Prozent |
| Inodes | Platte scheinbar frei, trotzdem "No space left on device" | df --output=ipcent,target | ab 85 Prozent |
| Freier Arbeitsspeicher | Der OOM-Killer trifft selten den Prozess, den Sie opfern würden | MemAvailable in /proc/meminfo | unter 200 MB |
| Systemlast | Zeigt Stau an, unabhängig davon ob CPU oder Platte die Ursache ist | drittes Feld in /proc/loadavg | 15-Minuten-Mittel über zweifacher Kernzahl |
| Fehlgeschlagene Dienste | Ein Dienst, der nachts stirbt, bleibt sonst bis zum Morgen tot | systemctl is-system-running | alles außer running |
| Zertifikatsablauf | Sperrt schlagartig jeden Besucher aus, nicht nur einen Teil | openssl x509 -checkend | unter 21 Tagen Restlaufzeit |
| Erreichbarkeit von außen | Beantwortet als einzige Prüfung, ob der Server noch da ist | zweiter Host, curl | zwei Fehlschläge in Folge |
Nicht auf der Liste steht die CPU-Auslastung in Prozent: Ein Server, der 100 Prozent zieht, weil ein Videokodierer läuft, arbeitet wie vorgesehen. Netzwerkdurchsatz und Prozessanzahl fehlen aus demselben Grund. Beides hilft bei der Ursachensuche, taugt aber nicht als Alarm, weil es keinen Wert gibt, ab dem Sie zwingend handeln müssten.
Der Rückweg, bevor die erste Datei entsteht
Überwachung ist ein lesender Vorgang und kann im Normalfall nichts kaputtmachen. Drei Dinge können es trotzdem.
Ein Skript, das repariert statt zu melden. Der Gedanke ist verführerisch: Wenn nginx tot ist, soll das Skript ihn eben neu starten. Daraus wird ein Dienst, der alle zehn Minuten startet, eine halbe Sekunde läuft und die Ursache verdeckt. Und ein Skript, das bei voller Platte selbstständig löscht, löscht irgendwann etwas, das gebraucht wurde. Die erste Fassung liest ausschließlich und ruft weder systemctl restart noch rm noch kill auf.
Offene Netzwerkschnittstellen. Metrik-Exporter, die auf allen Adressen lauschen, sind eine der häufigsten unbeabsichtigten Datenveröffentlichungen auf Einzelservern. Das Verfahren hier öffnet keinen Port und braucht keine Firewall-Regel.
Der Alarmweg selbst. Eine Überwachung, deren Benachrichtigung nie getestet wurde, ist keine Überwachung, sondern ein gutes Gefühl. Der Test dafür steht weiter unten und ist nicht optional.
Wie Sie ohne SSH auf den Server kommen
KVM-Rootserver und Dedicated Server haben weder IPMI noch iDRAC. Der Zugang, wenn SSH nicht mehr antwortet, ist die VNC-Konsole im Kundenbereich. Sie hängt nicht am Netzwerkstack des Gastsystems, eine Firewall-Regel oder ein überlasteter SSH-Dienst können sie also nicht blockieren. Melden Sie sich dort einmal vorher an und vergewissern Sie sich, dass Sie das root-Passwort kennen.
Der Ausschalter
Falls die Überwachung selbst zum Problem wird, etwa weil sie im Minutentakt Alarme verschickt, brauchen Sie zwei Befehle. Merken Sie sich diese, bevor Sie anfangen:
systemctl disable --now kh-monitor.timer
systemctl mask kh-monitor.service
Der erste beendet den Timer sofort und verhindert, dass er beim nächsten Start wiederkommt. Der zweite ist die Notbremse: Ein maskierter Dienst lässt sich auch nicht mehr versehentlich von Hand starten, zurückgenommen mit systemctl unmask kh-monitor.service. Risikoarm ist das Verfahren vor allem deshalb, weil ausschließlich neue Dateien entstehen; der Rückbau besteht aus dem Löschen dieser Dateien. Halten Sie trotzdem eine zweite SSH-Sitzung offen, solange Sie am System arbeiten.
Die Kennzahlen erst von Hand prüfen
Bevor ein Skript etwas auswertet, sollten Sie jeden Wert einmal selbst gesehen haben. Sonst wissen Sie später nicht, ob ein Alarm berechtigt ist oder ob Ihre Schwelle Unsinn ist.
Plattenplatz und Inodes
df -h
df --output=pcent,target -x tmpfs -x devtmpfs -x squashfs -x overlay
df -i
Die Ausschlüsse sind notwendig. Unter Ubuntu 22.04 und 24.04 bindet snap seine Pakete als schreibgeschützte squashfs-Abbilder ein, und die stehen dauerhaft bei 100 Prozent. Ohne -x squashfs meldet Ihre Überwachung ab dem ersten Lauf eine volle Platte, jeden Tag, für immer. Für die overlay-Einhängepunkte von Docker gilt dasselbe.
Zwei Eigenheiten sollten Sie kennen. df akzeptiert -P und --output nicht gemeinsam und bricht mit einer Meldung über sich gegenseitig ausschließende Optionen ab. Und auf ext4 sind ab Werk fünf Prozent für root reserviert, weshalb df bereits 100 Prozent meldet, während root noch schreiben kann. Was nach dem Alarm zu tun ist, steht in Festplatte voll unter Linux.
Die Inode-Prüfung ist kein Randthema. Ein Verzeichnis mit Millionen winziger Sitzungs- oder Cache-Dateien kann alle Inodes verbrauchen, während df -h reichlich freien Platz zeigt. Schreibvorgänge scheitern dann mit No space left on device, und die naheliegende Erklärung ist die falsche.
Arbeitsspeicher
free -m
awk '/^MemAvailable:/ { printf "%d MB\n", $2 / 1024 }' /proc/meminfo
Die Spalte free ist auf einem gesunden Linux-System fast immer klein, weil der Kernel ungenutzten Speicher als Dateicache verwendet. Belastbar ist nur available beziehungsweise MemAvailable: die Menge Speicher, die eine neue Anwendung bekommen kann, ohne dass etwas ausgelagert wird. Alarmieren Sie auf diesen Wert, nie auf free.
Ob es früher schon eng war, verrät das Kernel-Log:
journalctl -k -b --grep "Out of memory"
Jede Fundstelle ist ein Prozess, den der Kernel beendet hat, weil der Speicher ausging. Wie Sie reagieren, ohne blind Swap anzulegen, steht in Out of Memory und Swap richtig einrichten.
Systemlast
nproc
cat /proc/loadavg
uptime
Die ersten drei Felder in /proc/loadavg sind die Mittelwerte über eine, fünf und fünfzehn Minuten. Zwei Dinge werden regelmäßig missverstanden. Erstens ist die Last unter Linux keine reine CPU-Größe: Prozesse, die auf Plattenzugriffe warten, zählen mit. Eine Last von 20 auf vier Kernen kann heißen, dass die CPU brennt, oder dass ein Datenträger klemmt. Zweitens taugt der Ein-Minuten-Wert nicht für Alarme, weil jeder Sicherungslauf ihn kurz nach oben treibt. Nehmen Sie das 15-Minuten-Mittel und die Schwelle relativ zur Kernzahl.
Bringt Ihr Kernel die Stau-Statistik mit, ist sie aussagekräftiger, weil sie CPU, Ein- und Ausgabe sowie Speicher getrennt ausweist. Vorhanden ist sie nicht überall:
test -d /proc/pressure && cat /proc/pressure/io || echo "keine Stau-Statistik in diesem Kernel"
Dienste
systemctl is-system-running
systemctl --failed --no-pager
systemctl is-active nginx
systemctl is-system-running ist die kürzeste sinnvolle Gesamtprüfung. Sie gibt running aus, wenn keine einzige Unit im Fehlerzustand ist, und degraded, sobald eine es ist. Der Rückgabewert ist entsprechend 0 oder ungleich 0.
Zwei Fallstricke. Der Zustand degraded bleibt bestehen, bis Sie ihn nach der Reparatur mit systemctl reset-failed zurücksetzen; eine einmal fehlgeschlagene Aufgabe hält die Meldung sonst wochenlang aufrecht. Und beim Prüfen einzelner Dienste unterscheiden sich die Bezugssysteme: Unter Ubuntu 24.04 wird SSH per Socket-Aktivierung gestartet, ssh.service ist dort im Ruhezustand inactive, obwohl SSH einwandfrei erreichbar ist. Wer dort ssh.service überwacht, bekommt einen Dauerfehlalarm. Zu überwachen ist auf Ubuntu 24.04 ssh.socket, auf Debian 12, Debian 13 und Ubuntu 22.04 dagegen ssh.service.
Zertifikatsablauf
openssl x509 -enddate -noout -in /etc/letsencrypt/live/example.com/fullchain.pem
openssl x509 -checkend 1814400 -noout -in /etc/letsencrypt/live/example.com/fullchain.pem
Der zweite Befehl ist der interessante. -checkend erwartet eine Anzahl Sekunden, 1814400 sind 21 Tage. Läuft das Zertifikat innerhalb dieser Frist ab, gibt der Befehl Certificate will expire aus und liefert den Rückgabewert 1, andernfalls Certificate will not expire und 0. /etc/letsencrypt/live und /etc/letsencrypt/archive sind nur für root lesbar.
Die Prüfung hat eine Lücke, die viele Anleitungen unterschlagen: Sie prüft die Datei auf der Platte, nicht das Zertifikat, das Ihr Webserver ausliefert. Läuft die Verlängerung durch, scheitert aber der Reload des Webservers, ist die Datei neu und der ausgelieferte Schlüssel alt. Die Dateiprüfung meldet nichts, während Besucher bereits eine Zertifikatswarnung sehen. Nur der Blick von außen fängt diesen Fall:
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -enddate
-servername ist nicht optional, sobald mehrere Zertifikate auf einer IP-Adresse liegen. Ohne diesen Zusatz bekommen Sie das Standardzertifikat des Servers und prüfen die falsche Domain.
Das Prüfskript
Alle Prüfungen zusammen ergeben ein Skript, das nichts weiter tut als lesen, vergleichen und im Fehlerfall melden. Es braucht curl und, für den Webhook-Weg, jq. Auf minimalen Debian-Installationen fehlt beides:
apt update
apt install -y curl jq
cat > /usr/local/sbin/kh-monitor <<'EOF'
#!/bin/bash
set -u
DISK_WARN="${DISK_WARN:-85}"
INODE_WARN="${INODE_WARN:-85}"
MEM_MIN_MB="${MEM_MIN_MB:-200}"
LOAD_FACTOR="${LOAD_FACTOR:-2}"
CERT_DAYS="${CERT_DAYS:-21}"
UNITS="${UNITS:-ssh nginx}"
STATE_DIR="${STATE_DIRECTORY:-/var/lib/kh-monitor}"
problems=""
add() { problems+="- ${1}"$'\n'; }
notify() {
printf '%s | %s\n' "$1" "$(printf '%s' "$2" | tr '\n' ' ')"
if [ -n "${WEBHOOK_URL:-}" ]; then
printf '%s\n%s' "$1" "$2" | jq -Rs '{text: .}' \
| curl -fsS -m 10 -o /dev/null -H 'Content-Type: application/json' \
--data-binary @- "$WEBHOOK_URL"
fi
if [ -n "${MAILTO:-}" ]; then
printf '%s\n' "$2" | mail -s "$1" "$MAILTO"
fi
}
while read -r pcent target; do
pcent="${pcent%\%}"
case "$pcent" in ''|*[!0-9]*) continue ;; esac
[ "$pcent" -ge "$DISK_WARN" ] && add "Platte ${target} zu ${pcent} Prozent belegt"
done < <(df --output=pcent,target -x tmpfs -x devtmpfs -x squashfs -x overlay | tail -n +2)
while read -r ipcent target; do
ipcent="${ipcent%\%}"
case "$ipcent" in ''|*[!0-9]*) continue ;; esac
[ "$ipcent" -ge "$INODE_WARN" ] && add "Inodes auf ${target} zu ${ipcent} Prozent belegt"
done < <(df --output=ipcent,target -x tmpfs -x devtmpfs -x squashfs -x overlay | tail -n +2)
mem_avail=$(awk '/^MemAvailable:/ { printf "%d", $2 / 1024 }' /proc/meminfo)
[ "${mem_avail:-0}" -lt "$MEM_MIN_MB" ] && add "nur ${mem_avail} MB Arbeitsspeicher verfügbar"
cores=$(nproc)
load15=$(awk '{ print $3 }' /proc/loadavg)
awk -v l="$load15" -v c="$cores" -v f="$LOAD_FACTOR" 'BEGIN { exit !(l > c * f) }' \
&& add "Last im 15-Minuten-Mittel ${load15} bei ${cores} Kernen"
sysstate=$(systemctl is-system-running)
[ "$sysstate" = "running" ] || add "systemd meldet Zustand ${sysstate}"
for unit in $UNITS; do
systemctl is-active --quiet "$unit" || add "Dienst ${unit} ist $(systemctl is-active "$unit")"
done
for cert in /etc/letsencrypt/live/*/fullchain.pem; do
[ -r "$cert" ] || continue
openssl x509 -checkend $(( CERT_DAYS * 86400 )) -noout -in "$cert" >/dev/null 2>&1 \
|| add "Zertifikat ${cert} läuft in weniger als ${CERT_DAYS} Tagen ab"
done
mkdir -p "$STATE_DIR"
now=$(printf '%s' "$problems" | sha256sum | cut -d' ' -f1)
before=$(cat "${STATE_DIR}/last" 2>/dev/null || true)
printf '%s' "$now" > "${STATE_DIR}/last"
if [ -z "$problems" ]; then
[ -n "${HEARTBEAT_URL:-}" ] && curl -fsS -m 10 -o /dev/null "$HEARTBEAT_URL"
[ -n "$before" ] && [ "$now" != "$before" ] \
&& notify "Entwarnung $(hostname -s)" "Alle Prüfungen wieder ohne Befund."
exit 0
fi
[ "$now" = "$before" ] && exit 0
notify "Warnung $(hostname -s)" "$problems"
EOF
Vier Stellen verdienen eine Erklärung.
- Die Schleifen lesen aus
< <( ... ), nicht aus einer Pipe. Eine Pipe verlagert die Schleife in eine Subshell, die dort gesammelten Meldungen wären nach demdoneverschwunden. Der Fehler ist tückisch, weil das Skript fehlerfrei durchläuft und nur nie etwas meldet. - Die Schwellen lesen sich aus der Umgebung. Sie können jede Grenze für einen einzelnen Aufruf überschreiben. Darauf beruht der Alarmtest weiter unten.
- Der Zustand wird als Prüfsumme abgelegt. Gemeldet wird nur, wenn sich die Liste der Probleme geändert hat. Sonst schickt Ihnen eine volle Platte alle zehn Minuten dieselbe Nachricht, und Sie schalten die Überwachung nach zwei Tagen ab.
- Die Zertifikatsschleife läuft ins Leere, wenn kein Let's-Encrypt-Verzeichnis existiert. Das Muster bleibt unaufgelöst,
[ -r "$cert" ]schlägt fehl, der Durchlauf wird übersprungen.
Prüfen Sie jetzt, bevor systemd ins Spiel kommt:
chmod 700 /usr/local/sbin/kh-monitor
bash -n /usr/local/sbin/kh-monitor && echo "Syntax ok"
/usr/local/sbin/kh-monitor; echo "Rückgabewert $?"
Auf einem gesunden Server gibt der dritte Befehl außer Rückgabewert 0 nichts aus. Sehen Sie eine Meldung, ist entweder etwas nicht in Ordnung, oder eine Schwelle passt nicht, etwa weil in UNITS ein Dienst steht, den es hier nicht gibt.
Der systemd-Timer
Ein Cronjob täte es auch. Ein Timer hat aber vier konkrete Vorteile: Er startet keine zweite Instanz, solange die erste läuft, er holt einen verpassten Lauf nach einem Neustart nach, seine Ausgabe landet im Journal, und er lässt sich mit einem Befehl abschalten. Die Dienst-Unit braucht keinen [Install]-Abschnitt, weil sie nicht beim Systemstart, sondern vom Timer aktiviert wird.
cat > /etc/systemd/system/kh-monitor.service <<'EOF'
[Unit]
Description=Kurze Zustandspruefung des Servers
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/kh-monitor
EnvironmentFile=-/etc/default/kh-monitor
StateDirectory=kh-monitor
SyslogIdentifier=kh-monitor
Nice=10
IOSchedulingClass=idle
EOF
cat > /etc/systemd/system/kh-monitor.timer <<'EOF'
[Unit]
Description=Fuehrt kh-monitor regelmaessig aus
[Timer]
OnCalendar=*:0/10
RandomizedDelaySec=60
Persistent=true
[Install]
WantedBy=timers.target
EOF
StateDirectory=kh-monitor legt /var/lib/kh-monitor mit passenden Rechten an und setzt die Variable STATE_DIRECTORY, auf die das Skript zurückgreift. Das vorangestellte Minuszeichen in EnvironmentFile=-/etc/default/kh-monitor bedeutet, dass eine fehlende Datei kein Fehler ist. RandomizedDelaySec=60 streut den Startzeitpunkt, Persistent=true holt einen während einer Abschaltung verpassten Lauf beim Hochfahren nach.
Der Timer aktiviert den gleichnamigen Dienst automatisch, eine Unit=-Zeile ist nicht nötig:
systemd-analyze verify /etc/systemd/system/kh-monitor.service
systemd-analyze calendar '*:0/10'
systemctl daemon-reload
systemctl start kh-monitor.service
systemctl enable --now kh-monitor.timer
Erfolgskontrolle:
systemctl list-timers kh-monitor.timer --no-pager
journalctl -u kh-monitor.service -n 20 --no-pager
Die Liste muss eine Zeile mit dem nächsten Ausführungszeitpunkt zeigen. Bleibt sie leer, ist der Timer nicht aktiv. systemd-analyze calendar findet Tippfehler im Zeitausdruck: Es rechnet ihn in eine Normalform um und nennt den nächsten Termin. Einzelheiten zu Unit-Dateien und ihren Fehlerbildern stehen in systemd-Service erstellen.
Der Benachrichtigungsweg
Hier scheitern die meisten selbstgebauten Überwachungen. Der Melder läuft auf dem Server, den er überwacht, fällt also mit ihm aus. Damit meldet er alles zuverlässig außer dem einen Fall, der wirklich zählt.
Die Antwort heißt Totmannschalter: Der Server meldet sich nach jedem erfolgreichen Lauf bei einer Gegenstelle, und bleibt die Meldung aus, schlägt die Gegenstelle Alarm. Das Skript oben tut das, wenn HEARTBEAT_URL gesetzt ist. Netzausfall, hängendes Dateisystem und abgestürztes System sehen für die Gegenstelle gleich aus, und über alle drei wollen Sie Bescheid wissen.
Die Zugangsdaten gehören in eine eigene Datei, nicht ins Skript. Eine Webhook-Adresse ist ein Geheimnis, wer sie hat, kann in Ihrem Namen Nachrichten schicken:
cat > /etc/default/kh-monitor <<'EOF'
WEBHOOK_URL=https://beispiel.example/hooks/xxxxxxxx
HEARTBEAT_URL=https://beispiel.example/heartbeat/xxxxxxxx
UNITS="ssh nginx"
EOF
chmod 600 /etc/default/kh-monitor
Die Anführungszeichen um UNITS sind wichtig: systemd käme auch ohne sie zurecht, aber beim Testlauf weiter unten wird die Datei von der Shell eingelesen, und dort würde nginx ohne Anführungszeichen als Befehl aufgefasst. Tragen Sie nur Units ein, die es auf diesem System gibt, auf Ubuntu 24.04 also ssh.socket statt ssh.
Wer E-Mail bevorzugt, braucht einen Versandweg. Ein vollwertiger Mailserver ist überdimensioniert, ein reiner Weiterleiter genügt:
apt install -y msmtp msmtp-mta bsd-mailx
Konfiguriert wird das in /etc/msmtprc mit den Zugangsdaten eines vorhandenen Postfachs. Die Datei enthält ein Passwort und gehört auf chmod 600, sonst verweigert msmtp den Dienst mit einem Hinweis auf die Dateirechte. Zwei ehrliche Einschränkungen: E-Mail von einer frisch vergebenen Server-IP-Adresse landet häufig im Spam-Ordner oder wird abgewiesen, und eine Nachricht, die Sie erst beim nächsten Blick ins Postfach sehen, ist bei einem Ausfall zu langsam. Für Alarme ist Push-Zustellung die praktischere Wahl.
Den Alarm einmal auslösen
Dieser Schritt ist nicht optional. Erzwingen Sie eine Meldung, indem Sie eine Schwelle für einen einzelnen Aufruf unsinnig setzen:
set -a; . /etc/default/kh-monitor; set +a
DISK_WARN=0 /usr/local/sbin/kh-monitor
rm -f /var/lib/kh-monitor/last
Die Nachricht muss jetzt tatsächlich bei Ihnen ankommen, nicht nur im Journal stehen. Die dritte Zeile löscht den gespeicherten Zustand, damit der Testalarm den nächsten echten Lauf nicht unterdrückt. Ein Nebeneffekt ist Absicht: Schlägt die Zustellung fehl, endet kh-monitor.service mit einem Fehler und taucht in systemctl --failed auf. Ein stiller Benachrichtigungsweg wäre der schlimmste denkbare Fehler in einer Überwachung.
Die Sicht von außen
Der Totmannschalter sagt Ihnen, dass der Server lebt. Er sagt nicht, dass Ihre Website antwortet. Dafür braucht es eine Prüfung von einem anderen Standort aus, mit demselben Muster aus Skript und Timer, nur auf einem zweiten Host:
curl -fsS -m 10 -o /dev/null -w '%{http_code} %{time_total}\n' https://example.com/
Vier Punkte entscheiden über den Wert dieser Prüfung. Erstens: Prüfen Sie den echten Dienst, nicht nur ICMP. Ein Server, der auf Ping antwortet, während der Webserver in einer Endlosschleife hängt, gilt bei einer Ping-Prüfung als gesund. Zweitens: -f lässt curl bei HTTP-Fehlercodes fehlschlagen, ohne diesen Schalter gilt auch eine Fehlerseite als Erfolg. Drittens: Alarmieren Sie erst nach zwei Fehlschlägen in Folge, sonst meldet jede kurze Netzstörung einen Ausfall. Viertens: Ein Aufruf im Minutentakt von derselben Adresse kann in einer Ratenbegrenzung landen oder von einer Sperrsoftware als Angriff gewertet werden; tragen Sie die Adresse des prüfenden Hosts als Ausnahme ein.
Ohne zweiten Server bleibt ein gehosteter Prüfdienst. Kostenlose Angebote prüfen meist im Fünf-Minuten-Takt, Sie erfahren von einem Ausfall also entsprechend verzögert. Für einen einzelnen Server reicht das, und es ist besser als die Alternative, es gar nicht zu erfahren.
Häufige Fehler und Lösungen
Failed to start kh-monitor.service: Unit kh-monitor.service not found.: Nach dem Anlegen oder Ändern einer Unit fehlt systemctl daemon-reload. Zweithäufigste Ursache ist ein falsches Verzeichnis; eigene Units gehören nach /etc/systemd/system/.
The unit files have no installation config: Sie haben systemctl enable kh-monitor.service statt kh-monitor.timer aufgerufen. Der Dienst hat bewusst keinen [Install]-Abschnitt, aktiviert wird der Timer.
code=exited, status=203/EXEC: systemd konnte die Datei nicht ausführen. Entweder stimmt der Pfad in ExecStart nicht, oder chmod 700 fehlt, oder die Datei wurde unter Windows bearbeitet und trägt Zeilenenden mit Wagenrücklauf. Dagegen hilft sed -i 's/\r$//' /usr/local/sbin/kh-monitor.
Syntax error: redirection unexpected: Das Skript wurde mit sh statt bash gestartet. Unter Debian und Ubuntu ist /bin/sh die Shell dash, und die kennt weder < <( ... ) noch += bei Zeichenketten. Die erste Zeile muss #!/bin/bash lauten.
bash: mail: command not found: Es ist kein Mailprogramm installiert. Der Befehl mail stammt je nach System aus bsd-mailx oder mailutils, und die beiden unterscheiden sich in ihren Schaltern. Bleiben Sie bei -s für den Betreff.
curl: (22) The requested URL returned error: 404: Die Webhook-Adresse ist falsch oder auf der Gegenstelle gelöscht. Ohne -f hätte curl den Fehler stillschweigend geschluckt.
curl: (60) SSL certificate problem: certificate has expired: Bei der Prüfung von außen kein Werkzeugfehler, sondern der gesuchte Befund. Gegen den eigenen Webhook deutet dieselbe Meldung auf eine falsche Uhrzeit des prüfenden Servers hin.
Certificate will expire: Reguläre Ausgabe von openssl x509 -checkend mit Rückgabewert 1. Prüfen Sie, ob die Verlängerung noch läuft und der Webserver danach neu geladen wird.
Failed to parse calendar specification: Der Ausdruck hinter OnCalendar= ist ungültig. Testen Sie ihn einzeln mit systemd-analyze calendar, bevor er in die Unit wandert.
Warning: Stopping kh-monitor.service, but it can still be activated by: kh-monitor.timer: Sie haben den Dienst gestoppt statt den Timer. Der Dienst läuft ohnehin nur Sekunden, abzuschalten ist der Timer.
Alarm bei jedem Lauf, obwohl sich nichts geändert hat: Der Zustand wird nicht gespeichert. Prüfen Sie, ob StateDirectory=kh-monitor in der Unit steht und ob /var/lib/kh-monitor/last existiert und beschreibbar ist.
Kein Alarm, obwohl offensichtlich etwas kaputt ist: Lösen Sie die erzwungene Meldung von oben aus. Bleibt auch die aus, liegt es am Zustellweg, nicht an den Prüfungen.
Unterschiede zwischen den vier Systemen
| System | SSH-Unit, die zu überwachen ist | squashfs-Einhängepunkte | Wo die Meldungen landen |
|---|---|---|---|
| Debian 13 (trixie) | ssh.service, einzelne Abbilder nutzen ssh.socket | in der Regel keine | nur Journal, rsyslog fehlt in minimalen Installationen |
| Debian 12 (bookworm) | ssh.service | in der Regel keine | Journal, rsyslog je nach Installationsvariante |
| Ubuntu 24.04 LTS | ssh.socket | meist vorhanden, Ausschluss nötig | Journal und rsyslog |
| Ubuntu 22.04 LTS | ssh.service | meist vorhanden, Ausschluss nötig | Journal und rsyslog |
Gleich ist auf allen vier Systemen: systemd-analyze, StateDirectory= und RandomizedDelaySec= sind vorhanden, Skript und Unit-Dateien laufen unverändert.
Wann sich der große Werkzeugkasten lohnt
Was Sie jetzt haben, hat klare Grenzen. Es speichert keinen Verlauf, Sie können also nicht nachsehen, ob der Speicherverbrauch seit drei Wochen steigt. Es kennt keine Korrelation über mehrere Hosts. Und es hat weder Eskalation noch Bereitschaftsregeln noch eine Möglichkeit, einen bekannten Alarm für zwei Stunden stummzuschalten.
Genau diese Punkte beantworten die Frage nach dem Umstieg. Ein Metrik- und Dashboard-Aufbau lohnt sich, sobald einer davon zutrifft:
- Sie betreiben mehr als eine Handvoll Server und wollen sie nebeneinander sehen.
- Sie brauchen Verlauf und Trends, etwa für Kapazitätsplanung oder um einer Beschwerde über Langsamkeit mit Zahlen zu begegnen.
- Mehrere Personen teilen sich die Bereitschaft, es braucht also Eskalationsstufen und Stummschaltung.
- Sie müssen Verfügbarkeit gegenüber Dritten belegen.
Trifft nichts davon zu, ist der Aufbau für einen einzelnen Server meist ein schlechtes Geschäft. Sammelstelle, Datenbank, Dashboard und Exporter belegen zusammen leicht mehrere hundert Megabyte Arbeitsspeicher auf genau der Maschine, deren freien Speicher sie überwachen sollen. Dazu kommen ein weiterer offener Port und eine zweite Software, die aktualisiert werden will. Der entscheidende Punkt bleibt unverändert: Läuft die Sammelstelle auf demselben Server, meldet sie dessen Ausfall genauso wenig wie ein Skript. Beim Umstieg gehört die Sammelstelle auf einen anderen Host, und der Exporter bindet sich an 127.0.0.1 oder ist per Firewall auf deren Adresse beschränkt.
Der Mittelweg funktioniert gut: Timer und Skript bleiben, weil sie den Alarmfall abdecken, der Metrik-Aufbau kommt dazu, wenn Sie Verläufe brauchen. Beides schließt sich nicht aus.
Rückbau
Falls Sie das Verfahren wieder loswerden wollen, sind es fünf Zeilen:
systemctl disable --now kh-monitor.timer
rm -f /etc/systemd/system/kh-monitor.timer /etc/systemd/system/kh-monitor.service
rm -f /usr/local/sbin/kh-monitor /etc/default/kh-monitor
rm -rf /var/lib/kh-monitor
systemctl daemon-reload
Die Abschlusskontrolle
Sechs Prüfungen, die den tatsächlichen Zustand zeigen und nicht den erhofften:
systemctl list-timers kh-monitor.timer --no-pagernennt einen nächsten Ausführungszeitpunkt.journalctl -u kh-monitor.service --since "1 hour ago" --no-pagerzeigt Läufe im erwarteten Abstand.- Ein erzwungener Alarm über
DISK_WARN=0kommt bei Ihnen an, nicht nur im Journal. - Nach einem
rebootläuft der Timer weiter, ohne dass Sie etwas tun. - Der Totmannschalter meldet sich: Timer stoppen und abwarten, ob die Gegenstelle Alarm schlägt.
systemctl --failed --no-pagerlistet nichts auf, insbesondere nichtkh-monitor.service.
Punkt fünf ist der unbequemste und der wichtigste. Eine Überwachung, deren Alarmfall nie eingetreten ist, ist eine Vermutung. Erst wenn Sie den Ausfall absichtlich herbeigeführt und die Nachricht erhalten haben, ist die Kette vom Server bis zu Ihrem Telefon nachweislich vollständig.
Häufige Fragen
Brauche ich für einen einzelnen Root Server wirklich einen Metrikserver mit Dashboard?
Warum ein systemd-Timer und kein Cronjob?
Meine Überwachung meldet dauerhaft eine volle Platte, obwohl genug frei ist. Woran liegt das?
Wie erfahre ich, dass der Server komplett ausgefallen ist?
Welche SSH-Unit muss ich überwachen?
Wie verhindere ich, dass ich alle zehn Minuten dieselbe Warnung bekomme?
Das Zertifikat auf der Platte ist gültig, Besucher sehen trotzdem eine Warnung. Wie kann das sein?
Wie schalte ich die Überwachung schnell wieder ab, wenn sie stört?
2026 KernelHost GmbH. Alle Rechte vorbehalten. Diese Anleitung ist urheberrechtlich geschützt. Eine Veröffentlichung auf anderen Webseiten, auch auszugsweise oder in bearbeiteter Form, ist ohne unsere schriftliche Zustimmung nicht gestattet. Zitate mit Quellenangabe und Link sind ausdrücklich willkommen.

