Crontab and curl: Add a Cuckoo Ping to Any Job
Updated
The quickest way to monitor an existing cron job is to append one curl call to its crontab line. When the job
succeeds, curl pings Cuckoo. When the job fails, hangs, or never starts, the ping does not arrive and you get an
alert. No agent, no code changes, only outbound HTTPS.
This guide shows a crontab line you can copy, explains every curl flag, and covers the environment pitfalls that make commands work in your shell but fail under cron.
How Cuckoo sees the job
Each check has a ping URL, https://cuckoo.metastic.ch/ping/YOUR-UUID, and a schedule (a period or a cron
expression with a time zone) plus a grace time. A ping marks the check as up. If no ping arrives before the schedule
and grace time have passed, the check goes down and alerts are sent by email, Slack, Discord or webhook.
The basic crontab line
Open your crontab with crontab -e and add the ping after the job:
# m h dom mon dow command
15 3 * * * /usr/local/bin/cleanup.sh && curl -fsS -m 10 --retry 5 -o /dev/null https://cuckoo.metastic.ch/ping/YOUR-UUID
&& means curl only runs when cleanup.sh exits with status 0. A failing job therefore produces no ping, and
Cuckoo alerts after the grace time.
What each curl flag does
| Flag | Purpose |
|---|---|
-f |
Treat HTTP 4xx/5xx responses as errors (non-zero exit) |
-s |
Silent: no progress meter in cron mail |
-S |
Still print an error message if something goes wrong |
-m 10 |
Give up on a single attempt after 10 seconds |
--retry 5 |
Retry transient failures (timeouts, HTTP 408, 429, 502, 503, 504) up to five times |
-o /dev/null |
Discard the response body |
Without -m, a broken network path can make curl hang for a long time. Without -o /dev/null, the response body
ends up in cron's output and possibly in an email.
Reporting failures immediately
Using && only tells Cuckoo about success. To be alerted as soon as a run fails, send the exit code instead.
Use ; so curl always runs, and append $?:
15 3 * * * /usr/local/bin/cleanup.sh; curl -fsS -m 10 --retry 5 -o /dev/null https://cuckoo.metastic.ch/ping/YOUR-UUID/$?
/ping/YOUR-UUID/0 counts as success; any other value from 1 to 255 marks the run as failed right away.
Do you need || true?
On a single crontab line, the ping is the last command, so its exit status only affects what cron logs. You usually
do not need || true there.
It matters inside scripts that use set -e. If the ping fails because of a network blip, set -e would abort the
script, and a ping problem would become a job failure. Guard it explicitly:
#!/usr/bin/env bash
set -euo pipefail
/usr/local/bin/sync-reports
curl -fsS -m 10 --retry 5 -o /dev/null https://cuckoo.metastic.ch/ping/YOUR-UUID || true
The rule of thumb: the job decides whether the run failed, not the monitoring call.
Environment pitfalls under cron
Cron starts commands with a minimal environment, which causes most "works in my terminal" problems.
- PATH is short. Typically
/usr/bin:/bin. Tools in/usr/local/binor~/.local/binare not found. SetPATHat the top of the crontab or use absolute paths. - The shell is
/bin/sh. Bash features like[[ ]], arrays orset -o pipefailfail underdash. SetSHELL=/bin/bashor call a script with a bash shebang. %is special. In a crontab command, an unescaped%becomes a newline. Writedate +\%For move the logic into a script.- No profile files.
~/.bashrcand~/.profileare not read, so variables like proxy settings or API tokens are missing.
A crontab header that avoids most of these:
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=ops@example.com
15 3 * * * /usr/local/bin/cleanup.sh && curl -fsS -m 10 --retry 5 -o /dev/null https://cuckoo.metastic.ch/ping/YOUR-UUID
MAILTO and output
Cron mails any output a job produces to MAILTO (by default the crontab owner), if the server has a working mail
transport. MAILTO="" disables mail entirely. Many servers have no mail transport configured, so cron mail is not
a reliable alert channel on its own. Cuckoo complements it: the missing ping is detected on Cuckoo's side,
independently of the server's mail setup.
If you redirect job output to a log file, keep curl quiet so it does not clutter mail:
0 * * * * /opt/app/bin/import >> /var/log/import.log 2>&1 && curl -fsS -m 10 --retry 5 -o /dev/null https://cuckoo.metastic.ch/ping/YOUR-UUID
Schedule and grace advice
Copy the cron expression from the crontab line into the check and set the time zone the server's cron uses
(timedatectl shows it). Choose a grace time that covers the longest normal run plus a margin: for a job that
usually takes two minutes, 10 to 15 minutes is reasonable. For long or variable jobs, add a /start ping and a
max runtime instead of a very large grace time.
Troubleshooting
- curl: command not found. Use
/usr/bin/curlor fixPATHin the crontab. curl: (60) SSL certificate problem. The CA bundle is missing, common in slim containers. Install theca-certificatespackage.- The check is late every day by one hour. The check's time zone does not match the server's, or a DST switch happened. Align both.
- Nothing in the dashboard. Run the exact crontab command with
env -i /bin/sh -c '...'to reproduce cron's empty environment.
FAQ
Can I use wget instead of curl?
Yes. wget -q -T 10 -t 5 -O /dev/null https://cuckoo.metastic.ch/ping/YOUR-UUID behaves similarly: quiet, ten
second timeout, five tries, response discarded. curl is used in these guides because it is installed almost everywhere.
Will a slow or failed ping delay my job?
Only by the time curl spends retrying, which -m 10 and --retry 5 keep bounded. Because the ping runs after the
job, a ping failure never changes the work the job already did.
Does the ping URL need to stay secret?
Treat it like a credential. Anyone with the URL can send success pings and hide real failures, so keep it out of public repositories and shared logs.
Related guides
- Cron Job Exit Code MonitoringSend a cron job's exit code to Cuckoo via /ping/YOUR-UUID/$?, attach the log tail with curl --data-binary and use set -o pipefail so pipes can't hide errors.
- Monitor Certbot Certificate RenewalMonitor certbot renew from a systemd timer or cron: why --deploy-hook and --post-hook fall short, and how to report the exit code (plus acme.sh).
- Monitor systemd Timers with CuckooMonitor systemd timers with heartbeat pings: ExecStartPre and ExecStartPost signals, OnFailure= or ExecStopPost with SERVICE_RESULT, Persistent= and journalctl.
- Send Cron Job Logs with a Cuckoo PingCapture a cron job's stdout and stderr, POST the last 10 KB with the heartbeat ping, redact secrets before sending and keep full logs locally with logger.