Monitoring cron jobů: heartbeat pattern v praxi
· 6 min čtení
HTTP monitoring nezjistí, že spadl noční cron. Heartbeat pattern obrací směr: cron se hlásí monitoringu, a pokud nezavolá včas, dostanete upozornění.
Problém: úlohy na pozadí bez HTTP endpointu
Typický backend má několik cest:
- Webové requesty (HTTP/HTTPS na server) - monitorujete je uptime checkem.
- Cron joby (denní záloha, měsíční fakturace, hodinová synchronizace) - nemají HTTP endpoint, externí monitoring je nedokáže sledovat.
- Workery (Celery, BullMQ, Sidekiq) zpracovávající frontu - rovněž bez HTTP.
Když cron spadne (překlep v crontabu, plný disk, chybějící proměnná prostředí (environment variable) nebo chyba importu po aktualizaci závislosti (dependency upgrade)), nikdo vás neupozorní. Dozvíte se to až v pondělí ráno, když si všimnete, že se přes víkend neodeslaly faktury.
Heartbeat pattern: cron pinguje monitoring
Princip je obrácený oproti normálnímu monitoringu:
- V monitorovací službě vytvoříte heartbeat monitor s očekávaným intervalem (například "každých 60 minut").
- Dostanete unikátní heartbeat URL:
https://epulz.io/heartbeat/abc123xyz. - Ve svém cron jobu na konci úspěšného běhu zavoláte tuto URL (HTTP GET nebo POST).
- Pokud ping nepřijde v očekávaném čase (plus grace perioda), monitoring vás upozorní.
Praktický příklad: heartbeat z cron jobu
# /etc/crontab
0 3 * * * www-data /usr/local/bin/backup.sh && curl -fsS -m 10 \
https://epulz.io/heartbeat/abc123xyz > /dev/null
Klíčový je operátor &&: heartbeat se odešle jen tehdy, když backup.sh skončí s exit kódem 0. Pokud skript selže, ping nepřijde a vy do hodiny dostanete upozornění.
Tip: Pro důkladnější pokrytí přidejte i "start" heartbeat:
curl -fsS -m 10 https://epulz.io/heartbeat/backup-start-xyz > /dev/null
/usr/local/bin/backup.sh && \
curl -fsS -m 10 https://epulz.io/heartbeat/backup-done-xyz > /dev/null
Monitoring pak rozliší "začal a nedokončil" (skript zamrzl) od "vůbec nezačal" (cron job se nespustil).
Python: requests + try/except
import os, requests
HEARTBEAT_URL = os.environ["HEARTBEAT_URL"]
def sync_data():
# ... your logic ...
pass
try:
sync_data()
requests.get(HEARTBEAT_URL, timeout=10)
except Exception as e:
# Heartbeat se neodešle - monitoring vás upozorní
raise
Node.js: async / await
const HEARTBEAT_URL = process.env.HEARTBEAT_URL;
async function nightlyJob() {
await processInvoices();
await fetch(HEARTBEAT_URL, { signal: AbortSignal.timeout(10000) });
}
nightlyJob().catch(err => {
console.error(err);
process.exit(1);
});
Grace perioda: kolik času dát před upozorněním
Heartbeat monitor potřebuje jistou toleranci. Cron občas běží déle než obvykle, síť má latenci a NTP synchronizace může být mírně posunutá. Grace perioda je čas po uplynutí očekávaného intervalu, během kterého monitoring ještě čeká, než spustí upozornění.
Praktické hodnoty:
- Hodinový cron: interval 60 min + grace 10 min
- Denní záloha (průměrně 20 min): interval 1440 min + grace 60 min
- Týdenní report: interval 10080 min + grace 360 min (6 h)
Příliš těsná grace = falešná upozornění (false positive). Příliš volná = opožděné upozornění ve chvíli, kdy úloha reálně spadne.
Kde heartbeat pattern nejvíce pomáhá
- Noční DB zálohy
- Synchronizace s externími API (CRM, accounting, payment)
- Kalkulace reportů
- Cleanup úlohy (mazání starých session, logů, dočasných souborů)
- Healthcheck cyklus dlouho běžících workerů
- Naplánované e-maily, newslettery, fakturace
Závěr
Úlohy na pozadí (background) bývají často kritičtější než samotný web, ale zůstávají slepou skvrnou monitoringu. Heartbeat pattern si vyžaduje jen pět minut na implementaci (stačí přidat curl na konec cron řádku) a poskytuje stejnou jistotu jako uptime monitoring frontendu.
Rychlá připomínka: syntaxe cronu
Většina chyb heartbeatu jsou ve skutečnosti chyby cronu - ping se nikdy nespustí, protože byl špatný rozvrh. Pět polí je:
┌── minuta (0-59)
│ ┌── hodina (0-23)
│ │ ┌── den v měsíci (1-31)
│ │ │ ┌── měsíc (1-12)
│ │ │ │ ┌── den v týdnu (0-7, 0 i 7 = neděle)
│ │ │ │ │
* * * * * příkaz
| Výraz | Spustí se |
|---|---|
*/5 * * * * |
každých 5 minut |
0 * * * * |
na začátku každé hodiny |
0 3 * * * |
každý den ve 03:00 |
0 3 * * 1 |
každé pondělí ve 03:00 |
30 2 1 * * |
ve 02:30 prvního dne v měsíci |
Klasická past: */5 v poli hodina neznamená "každých 5 hodin od teď", ale hodiny dělitelné pěti (0, 5, 10, 15, 20). Pokud se očekávaný interval monitoru a reálný rozvrh cronu neshodují, dostáváte fantomová upozornění.
Princip "dead man's switch"
Heartbeat pattern je dead man's switch (pojistka mrtvého muže): alarmem je ticho. To obrací běžný způsob selhání. Normální monitoring může selhat potichu - pokud spadne samotný monitorovací server, jednoduše přestane posílat upozornění a vy se to nikdy nedozvíte. Heartbeat je opak: spouštěčem upozornění je nepřítomnost očekávaného signálu, takže úloha, která přestane běžet úplně (celý server je vypnutý, cron démon zakázán, stroj byl vyřazen a zapomenut), je přesně ten případ, který zachytí nejlépe.
Mimo cron: další plánovače
Vzor je stejný bez ohledu na to, co úlohu spouští:
- systemd timery - přidejte curl do řetězce ExecStart nebo do ExecStartPost=. Spárujte OnCalendar= timer s odpovídajícím intervalem heartbeatu.
- Kubernetes CronJob - poslední krok kontejneru pingne heartbeat URL. Pokud pod spadne nebo se vůbec nenaplánuje (špatný node selector, selhání image pull), ping chybí a dostanete upozornění.
- Windows Task Scheduler - ukončete úlohu PowerShell příkazem Invoke-WebRequest -Uri $env:HEARTBEAT_URL -TimeoutSec 10.
- CI / plánované pipeline - noční GitHub Actions nebo GitLab schedule může jako poslední krok pingnout heartbeat a potvrdit, že pipeline proběhla i prošla.
Běžné anti-patterny
- Ping na začátku, ne na konci. Heartbeat odeslaný před prací dokazuje jen to, že úloha začala. Dejte ho za práci, podmíněný úspěchem (
&&), aby pád uprostřed běhu rovněž zadržel ping. - Ignorování exit kódu.
backup.sh; curl ...(středník) pošle ping i když záloha selhala. Vždy použijte&&. - Tiché spolknutí selhání curl.
-fsSzpůsobí, že curl při HTTP chybě selže nahlas, takže logy vaší úlohy ukážou, že heartbeat se nepodařilo doručit (síťový problém na stroji). - Jeden heartbeat pro deset úloh. Pokud pět cronů sdílí jednu URL, nevíte, který přestal běžet. Dejte každé naplánované úloze vlastní heartbeat. Pokud pro tutéž službu vystavujete i HTTP endpoint, spárujte heartbeat s běžným uptime checkem a port checkem na portu workeru, abyste pokryli i "běží proces" i "proběhl naplánovaný běh".
Konkrétní scénář: tiché selhání zálohy
Učebnicový případ pro heartbeat vypadá takto. Noční pg_dump zapisuje na připojený svazek. Měsíce to funguje. Pak se svazek zaplní, pg_dump skončí s nenulovým kódem, a protože cron řádek použil obyčejný středník, heartbeat se i tak odešle a dashboard zůstane zelený. Za tři týdny je databáze poškozená a neexistuje použitelná záloha, protože každá "úspěšná" záloha od chvíle, kdy se disk zaplnil, byla nulový soubor.
Heartbeat pattern toto zachytí už první noc, ale jen pokud je zapojený správně: podmiňte ping přes &&, aby nenulový exit ping zadržel, a zvažte kontrolu výstupu, nejen exit kódu. Zálohovací skript může skončit s kódem 0 a přesto vyprodukovat zkrácený soubor. Defenzivnější řádek ověří, že dump není triviální, ještě před signalizací úspěchu:
/usr/local/bin/backup.sh && \
test "$(stat -c%s /backups/db.sql.gz)" -gt 1000000 && \
curl -fsS -m 10 https://epulz.io/heartbeat/abc123xyz > /dev/null
Nyní heartbeat dorazí jen tehdy, pokud skript uspěl a zároveň má výsledný soubor přes 1 MB. Cokoli menšího a ping se zadrží, a vy dostanete upozornění do grace periody namísto o tři týdny později.
Začněte monitorovat cron joby
ePulz.io podporuje heartbeat checks s konfigurovatelnou grace periodou. 7 dní zdarma.
Související
Vyzkoušejte ePulz.io zdarma - 7 dní bez kreditní karty.
Vytvořit účet