Praxis · 11 Min. Lesezeit

Cronjobs mit Heartbeat überwachen: Anleitung

Kurz erklärt

Ein Heartbeat-Monitor dreht die Überwachung um: Ihr Cronjob ruft nach jedem erfolgreichen Lauf eine Ping-URL auf. Bleibt der Ping länger als das gewählte Intervall plus Karenzzeit (5 Minuten) aus, löst UPTIMESHIELD Alarm aus. So fallen Backups, Importe und Newsletter-Versand auf, die still nicht mehr laufen.

Das Wichtigste in Kürze

  • Ein Cronjob hat keine Adresse und keine Fehlerseite: Ohne Heartbeat bleibt sein Ausfall unsichtbar.
  • Senden Sie den Ping nur nach Erfolg am Ende des Skripts; ein Ping am Anfang beweist nichts.
  • Intervall = Abstand der Läufe, plus 5 Minuten Karenzzeit; bei schwankender Laufzeit das nächstgrößere Intervall wählen.
  • Die Ping-URL /ping/<TOKEN>/ braucht keine Anmeldung, ist aber wie ein Passwort zu behandeln.
  • Der Heartbeat belegt nur, dass das Skript bis zur Ping-Zeile kam, nicht dass das Ergebnis inhaltlich stimmt.

Was ist ein Heartbeat-Monitor?

Ein Heartbeat-Monitor (auch „Dead Man’s Switch“, „Cronjob-Monitor“ oder passive Überwachung) wartet darauf, dass ein System sich regelmäßig meldet. Anders als bei einem HTTP-Monitor ruft nicht der Monitor das Ziel auf, sondern Ihr Skript ruft den Monitor auf, in Form einer HTTP-Anfrage an eine eindeutige Ping-URL. Bleibt die Meldung länger als erwartet aus, schlägt der Monitor Alarm. Der Alarm entsteht also aus einem Ausbleiben, nicht aus einem Fehlerereignis, und genau das macht ihn für Hintergrundaufgaben geeignet.

Heartbeat ist einer von zehn Monitortypen von UPTIMESHIELD, neben HTTP, Keyword, API/JSON, SSL, DNS, TCP-Port und Domain-Ablauf; die Übersicht steht unter Monitortypen.

Warum fallen Cronjobs so oft unbemerkt aus?

Ein Webserver zeigt Fehler: eine Fehlerseite, einen Statuscode, eine Meldung im Log. Ein Cronjob hat nichts dergleichen. Läuft er nicht, passiert schlicht nichts, und Stille ist schwer zu erkennen. Typische Ursachen aus der Praxis:

  • Server oder Container neu aufgesetzt, die Crontab wurde nicht übernommen (häufig nach einem Umzug, siehe Relaunch und Umzug überwachen).
  • Pfad oder Benutzer geändert: Das Skript liegt nicht mehr dort, der Benutzer existiert nicht mehr oder hat keine Rechte.
  • Abweichende Umgebung: Im Cron ist PATH kleiner als in der Shell; php, mysqldump oder node werden nicht gefunden.
  • Das Skript bricht ab: Datenträger voll, Datenbank nicht erreichbar, Passwort geändert, Zertifikat abgelaufen.
  • Hängende Läufe: Ein Lauf blockiert (Lock, Netzwerk), der nächste wird nicht gestartet oder stapelt sich.
  • Zeitumstellung oder Zeitzone: Läuft der Cron in UTC und der Server in lokaler Zeit, verschieben sich Läufe. Bei Sommer-/Winterzeit-Wechsel kann ein Lauf ausfallen oder doppelt laufen.
  • Cron-Dienst gestoppt oder durch Updates deaktiviert.

Die Folge bemerkt man oft erst, wenn die Aufgabe gebraucht wird, etwa wenn das Backup wiederhergestellt werden soll und das letzte vor drei Monaten entstand. Wie viel ein solcher Ausfall kosten kann, hängt vom Einzelfall ab, siehe Was kostet ein Website-Ausfall?.

Wie funktioniert der Heartbeat bei UPTIMESHIELD?

  1. Legen Sie im Dashboard einen Heartbeat-Monitor an und wählen Sie das erwartete Intervall: 5, 10, 15, 30, 60, 120, 360, 720 oder 1.440 Minuten.
  2. Sie erhalten eine Ping-URL der Form https://uptimeshield.de/ping/<TOKEN>/. Sie braucht keine Authentifizierung und akzeptiert GET, POST und HEAD.
  3. Ihr Skript ruft diese URL nach erfolgreichem Lauf auf.
  4. Bleibt der Ping länger als Intervall plus Karenzzeit (5 Minuten) aus, wird die Störung bestätigt und an Ihre Kanäle gemeldet. Nach dem nächsten Ping gilt der Monitor wieder als erreichbar.

Bis zum ersten Ping steht der Status auf „Unbekannt“; der Monitor schlägt also nicht an, solange Sie ihn noch einrichten. Nutzen Sie den ersten Ping als Test, indem Sie die URL einmal im Browser oder mit curl -fsS aufrufen. Die Ping-Seite ist vom Prüfintervall der übrigen Monitore unabhängig; wann welche Benachrichtigung ausgelöst wird, steht unter Alarme & Kanäle.

Wie sieht der Ping in der Praxis aus?

Bash-Skript mit Fehlerabbruch

#!/bin/bash
set -euo pipefail           # bei jedem Fehler abbrechen: dann folgt kein Ping

/usr/local/bin/backup.sh    # eigentliche Aufgabe

# Erst wenn alles geklappt hat, den Heartbeat senden
curl -fsS -m 10 --retry 3 https://uptimeshield.de/ping/IHR_TOKEN/ > /dev/null

Die Optionen im Überblick: -f lässt curl bei HTTP-Fehlern mit Rückgabewert ungleich null enden, -sS unterdrückt den Fortschritt, zeigt aber Fehler, -m 10 begrenzt die Gesamtdauer auf 10 Sekunden, und --retry 3 wiederholt bei vorübergehenden Fehlern. Ohne -m kann ein Netzwerkproblem den Job selbst blockieren.

Direkt in der Crontab

# nächtlich 03:00 Uhr; Monitor-Intervall: 1440 Minuten
0 3 * * * /opt/scripts/nightly-backup.sh && curl -fsS -m 10 --retry 3 https://uptimeshield.de/ping/IHR_TOKEN/ > /dev/null

# alle 15 Minuten; Monitor-Intervall: 30 Minuten
*/15 * * * * /usr/bin/php /var/www/app/bin/sync.php && curl -fsS -m 10 https://uptimeshield.de/ping/IHR_TOKEN/ > /dev/null

Das && sorgt dafür, dass der Ping nur nach Rückgabewert 0 gesendet wird. Skripte müssen den Rückgabewert dafür korrekt setzen: Ein Skript, das Fehler schluckt und mit 0 endet, meldet Erfolg, obwohl nichts passiert ist.

Überlappende Läufe verhindern

*/5 * * * * flock -n /tmp/sync.lock /opt/scripts/sync.sh && curl -fsS -m 10 https://uptimeshield.de/ping/IHR_TOKEN/ > /dev/null

flock -n beendet sich mit Fehler, wenn der vorige Lauf noch läuft. Dann folgt kein Ping, und bei dauerhaft hängendem Lauf wird der Monitor ausgelöst. Das ist gewollt: Ein Job, der nie fertig wird, ist ein Ausfall.

PHP

<?php
// ... eigentliche Aufgabe, bei Fehler Exception werfen oder exit(1)
$ctx = stream_context_create(['http' => ['method' => 'GET', 'timeout' => 10]]);
@file_get_contents('https://uptimeshield.de/ping/IHR_TOKEN/', false, $ctx);

systemd-Timer

# /etc/systemd/system/backup.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
ExecStartPost=/usr/bin/curl -fsS -m 10 --retry 3 https://uptimeshield.de/ping/IHR_TOKEN/

ExecStartPost wird nur ausgeführt, wenn ExecStart erfolgreich war. Ein zugehöriger Timer (OnCalendar=*-*-* 03:00:00) startet die Unit.

Windows-Aufgabenplanung (PowerShell)

try {
    C:\Skripte\backup.ps1
    if ($LASTEXITCODE -eq 0) {
        Invoke-WebRequest -Uri "https://uptimeshield.de/ping/IHR_TOKEN/" -UseBasicParsing -TimeoutSec 10 | Out-Null
    }
} catch { exit 1 }

Auch Frameworks bringen Hilfen mit; Laravel etwa kennt an geplanten Aufgaben pingOnSuccess($url). Wichtig ist immer dasselbe Prinzip: Ping nach Erfolg.

Wie wählt man Intervall und Karenzzeit?

Der Alarm entsteht, wenn seit dem letzten Ping mehr Zeit vergangen ist als Intervall plus Karenzzeit. Die Karenzzeit beträgt 5 Minuten. Das Intervall wählen Sie aus der Liste (5, 10, 15, 30, 60, 120, 360, 720, 1.440 Minuten):

Cron-RhythmusEmpfohlenes Monitor-IntervallAlarm spätestens nach
jede Minute5 Minuten10 Minuten ohne Ping
alle 5 Minuten15 Minuten20 Minuten ohne Ping (3 verpasste Läufe)
alle 15 Minuten30 Minuten35 Minuten ohne Ping
stündlich120 Minuten125 Minuten ohne Ping
täglich1.440 Minuten1.445 Minuten (24 Std. 5 Min.)

Die Faustregel: Das Intervall sollte etwas größer sein als der Abstand der Läufe, damit ein einzelner verspäteter Lauf keinen Alarm auslöst, aber klein genug, dass ein echter Ausfall zeitnah auffällt.

Beispielrechnung: Wenn das Backup länger dauert

Ein nächtliches Backup startet um 03:00 Uhr und pingt am Ende. Am Montag dauert es 12 Minuten (Ping 03:12), am Dienstag wegen wachsender Daten 19 Minuten (Ping 03:19). Der Abstand der beiden Pings beträgt 24 Stunden und 7 Minuten, also 1.447 Minuten. Bei Intervall 1.440 und Karenzzeit 5 liegt die Schwelle bei 1.445 Minuten: Der Monitor schlägt Alarm, obwohl nichts kaputt ist. Lösung: den Ping zeitlich stabilisieren (zum Beispiel ein separater Ping vor dem langen Teil, siehe unten), Laufzeitschwankungen verringern oder die Aufgabe so planen, dass der Ping nach dem Backup in einem engeren Zeitfenster liegt. Eine pragmatische Alternative ist ein Cron, der täglich zweimal läuft, mit Intervall 720.

Beachten Sie: Bei seltenen Jobs (wöchentlich, monatlich) reicht das größte Intervall von 1.440 Minuten nicht. Dann bauen Sie einen täglichen Wrapper, der den Ping sendet, solange das letzte erfolgreiche Ergebnis des Jobs nicht zu alt ist, zum Beispiel anhand einer Zeitstempel-Datei:

# täglich prüfen, ob das wöchentliche Backup in den letzten 8 Tagen erfolgreich war
0 6 * * * find /var/backups/weekly -name "*.tar.gz" -mtime -8 | grep -q . && curl -fsS -m 10 https://uptimeshield.de/ping/IHR_TOKEN/ > /dev/null

Dieser Ping meldet nicht „der Job lief“, sondern „es gibt ein frisches Ergebnis“, die bessere Aussage, solange die Datei nicht von etwas anderem erzeugt wurde.

Was ist besser: Ping am Anfang oder am Ende?

Am Ende, nach Erfolg. Ein Ping am Anfang beweist nur, dass der Cron gestartet wurde, nicht, dass der Job durchlief. Bricht das Backup in der Mitte ab, wäre der Monitor trotzdem grün. Zwei Pings (Start und Ende) wären ideal, wenn der Dienst Laufzeiten auswerten würde; UPTIMESHIELD wertet einen Ping als Lebenszeichen und kennt keine getrennten Start-, Erfolgs- und Fehler-Signale. Die einfache Lösung ist deshalb: Ping am Ende, bei Fehler kein Ping, der Alarm folgt über das Ausbleiben. Wer zusätzlich eine klare Fehlermeldung braucht, schreibt sie aus dem Skript ins Log oder sendet selbst eine E-Mail oder einen Webhook.

Wie sichert man die Ping-URL ab?

Die Ping-URL enthält ihren Token und wird ohne weitere Anmeldung aufgerufen. Wer die URL kennt, kann Pings senden und damit einen Ausfall verdecken. Behandeln Sie sie wie ein Passwort:

  • Legen Sie sie nicht in öffentliche Repositories, Skripte auf Webservern oder Support-Tickets. Nutzen Sie Umgebungsvariablen oder eine Konfigurationsdatei mit Zugriffsrechten.
  • Vermeiden Sie, sie in Logs auszugeben (curl -v, Shell-Verlauf, CI-Protokolle).
  • Bei Verdacht auf Weitergabe legen Sie einen neuen Monitor mit neuem Token an und tauschen die URL aus.
  • Pro Ping-URL gilt ein Rate Limit (derzeit 600 Pings pro Stunde). Ein Cron im Minutentakt bleibt darunter; eine Schleife, die in Sekunden pingt, nicht.

Welche Fehler treten beim Heartbeat häufig auf?

  • Ping vor der Arbeit. Der Monitor bleibt grün, obwohl der Job abbricht. Gegenmaßnahme: Ping ans Ende, set -e oder &&.
  • Skript meldet 0 trotz Fehler. Ein || true oder verschluckte Fehler lassen den Ping durchgehen. Gegenmaßnahme: Rückgabewerte prüfen, bewusst fehlschlagen lassen.
  • Intervall zu knapp. Schwankende Laufzeiten lösen Fehlalarme aus (siehe Beispielrechnung). Gegenmaßnahme: nächstgrößeres Intervall.
  • Firewall blockiert ausgehende Verbindungen. Der Job läuft, der Ping kommt nicht an. Gegenmaßnahme: ausgehendes HTTPS zu uptimeshield.de erlauben, curl manuell als Cron-Benutzer testen.
  • Proxy oder Zertifikatsprobleme auf dem Server. Alte Systeme haben veraltete CA-Zertifikate. Gegenmaßnahme: CA-Bundle aktualisieren; -k (Zertifikatsprüfung abschalten) ist keine Lösung.
  • Cron-Umgebung. Relative Pfade, fehlendes PATH, falsche Zeitzone. Gegenmaßnahme: absolute Pfade, Variablen in der Crontab setzen (PATH=…, CRON_TZ=…, je nach Cron-Implementierung).
  • Kein Alarmkanal. Der Monitor wird rot, niemand erfährt es. Gegenmaßnahme: Kanal einrichten und testen, siehe Benachrichtigungen richtig einrichten.

Checkliste: Neuen Cronjob absichern

  1. Heartbeat-Monitor mit passendem Intervall anlegen, Ping-URL kopieren.
  2. Skript mit Fehlerabbruch (set -e / korrekten Rückgabewerten) versehen.
  3. Ping als letzten Schritt mit curl -fsS -m 10 --retry 3 hinzufügen.
  4. Befehl einmal als Cron-Benutzer manuell ausführen; Monitor muss von „Unbekannt“ auf „Erreichbar“ wechseln.
  5. Einen Fehler provozieren (falscher Pfad), prüfen, dass der Alarm nach Intervall plus Karenzzeit kommt.
  6. Alarmkanäle und Zuständigkeit festlegen.
  7. Token wie ein Passwort ablegen.
  8. Bei Änderungen an Zeitplan oder Laufzeit das Intervall prüfen.

Grenzen und Einordnung

Der Heartbeat hängt vom Ping-Sender ab: Fällt der Server aus oder blockiert eine Firewall den ausgehenden Aufruf, bleibt der Ping aus, auch wenn der Job lief; der Alarm zeigt dann das Ausbleiben, nicht dessen Ursache. Ein Ping belegt nur, dass das Skript bis zur Ping-Zeile gelangte. Ob das Backup vollständig und wiederherstellbar ist, ob der Import die richtigen Daten geschrieben hat, prüft er nicht; dafür brauchen Sie inhaltliche Kontrollen im Skript oder regelmäßige Wiederherstellungstests. Außerdem lassen sich keine Laufzeiten, Start-/Fehlersignale oder Ausgaben übermitteln. Und wie bei jedem Monitoring gilt: Die Erkennung dauert im ungünstigsten Fall bis zu Intervall plus Karenzzeit. Mehr zu den allgemeinen Grenzen: Grenzen automatischer Website-Prüfungen.

Wie setzt man das mit UPTIMESHIELD um?

Heartbeat-Monitore sind mit dem kostenlosen Solo-Konto verfügbar (bis zu 10 Monitore, Registrierung nötig). Legen Sie den Monitor im Dashboard an, ordnen Sie ihm Alarmkanäle zu und testen Sie die Kanäle. Mit Tags („backup“, „import“) behalten Sie viele Cronjobs im Blick, und das SLA-Ziel mit Fehlerbudget zeigt, wie oft ein Job im Zeitraum ausfallen durfte. Der Heartbeat lässt sich mit anderen Monitoren kombinieren: für WordPress zum Beispiel mit der Anleitung WordPress-Website überwachen. Einen Beispielaufruf zeigt auch die API-Dokumentation; die Ping-URL ist nicht Bearer-geschützt.

Quellen und weiterführende Standards

Externe Links führen zu den Original-Spezifikationen und offiziellen Dokumentationen. Die Einordnung und die Beispielrechnungen stammen aus der Messmethodik von UPTIMESHIELD.

Selbst prüfen: Testen Sie jetzt, ob Ihre Website erreichbar ist und wie schnell sie antwortet – mit dem Uptime Checker.

Häufige Fragen zum Thema

Muss die Ping-URL geheim bleiben?
Ja, behandeln Sie sie wie ein Passwort. Wer sie kennt, kann Pings senden und einen Ausfall verdecken. Bei Verdacht legen Sie einen neuen Monitor mit neuem Token an.
Kann ich auch Fehler melden statt nur Erfolg?
Der Monitor wertet das Ausbleiben des Pings. Senden Sie den Ping nur bei Erfolg, dann führt jeder Fehler zum Ausbleiben und damit zum Alarm nach Intervall plus Karenzzeit.
Funktioniert das auch ohne curl?
Ja. Jede HTTP-Anfrage per GET, POST oder HEAD genügt, zum Beispiel mit wget, aus einem PHP-Skript, PowerShell oder einem systemd-Dienst.
Welches Intervall wähle ich für einen täglichen Cronjob?
Wählen Sie 1.440 Minuten. Der Alarm kommt nach 1.445 Minuten ohne Ping (Intervall plus 5 Minuten Karenzzeit). Schwankt die Laufzeit stark, planen Sie den Ping zeitlich enger oder wählen einen häufigeren Lauf.
Was ist mit Jobs, die nur wöchentlich oder monatlich laufen?
Das größte Intervall beträgt 1.440 Minuten. Nutzen Sie einen täglichen Wrapper, der nur pingt, wenn ein frisches Ergebnis vorliegt, etwa eine Datei mit jungem Änderungsdatum.
Was passiert, wenn der Server selbst ausfällt?
Dann bleibt auch der Ping aus, und der Monitor schlägt nach Intervall plus Karenzzeit an. Er unterscheidet nicht zwischen ausgefallenem Server und ausgefallenem Job; ergänzen Sie einen HTTP- oder TCP-Monitor, um die Ursache einzugrenzen.