systemd timers are the modern replacement for cron on Linux systems. Like cron jobs, they fail silently by default. Alert24 heartbeat checks give you visibility: if a timer stops firing or its service exits with an error, Alert24 creates an incident.
Before you start
- In Alert24, go to Monitoring → Add check → Heartbeat
- Give it a name matching your service (e.g., "Data sync timer")
- Set the Expected interval to match your timer's
OnCalendarorOnBootSecfrequency - Set a Grace period (300 seconds is a safe default for hourly-or-less timers)
- Save — you'll get a heartbeat URL:
https://app.alert24.net/api/hb/YOUR_TOKEN
Add the ping to your service unit
Edit your service file (/etc/systemd/system/your-job.service) and add an ExecStartPost directive:
[Unit]
Description=Daily data sync
After=network.target
[Service]
Type=oneshot
User=app
ExecStart=/usr/local/bin/sync-data.sh
ExecStartPost=/bin/bash -c 'curl -fsS --retry 3 https://app.alert24.net/api/hb/YOUR_TOKEN || true'
[Install]
WantedBy=multi-user.target
The ExecStartPost line runs after ExecStart exits. Use || true to prevent the post step from masking the exit code of the main command.
Important:
ExecStartPostonly runs ifExecStartexits with code 0. If your service fails, no ping is sent — which is the correct behavior. Alert24 fires an incident after the grace period expires.
Alternative: OnSuccess handler (systemd 250+)
If you're on a recent systemd version, use OnSuccess to chain a ping unit:
# your-job.service
[Unit]
Description=Daily data sync
[email protected]
[Service]
Type=oneshot
ExecStart=/usr/local/bin/sync-data.sh
# /etc/systemd/system/[email protected]
[Unit]
Description=Alert24 heartbeat ping for %i
[Service]
Type=oneshot
ExecStart=/usr/bin/curl -fsS --retry 3 https://app.alert24.net/api/hb/%i
Your timer file stays unchanged
# your-job.timer
[Unit]
Description=Run data sync daily
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
Reload and restart after changes:
systemctl daemon-reload
systemctl restart your-job.timer
Tips
journalctl -u your-job.service: Use this to view logs if the service fails and the ping is never sent.Persistent=true: With this set, if the system was off when the timer was supposed to fire, it runs immediately on next boot. Alert24's grace period accommodates brief system downtime — set it longer than your typical maintenance window.- Multiple services: Create one Alert24 heartbeat check per timer service. The
[email protected]pattern (Option 2) makes it easy to add a ping to any service without duplicating configuration.