Every cron job monitor has its own ping URL, shown on its page. Replace https://app.uptimecheck.com/api/hb/your-token below with yours. To create the monitor, see how to monitor a cron job.
The URLs
…/your-token: the job ran and succeeded.…/your-token/start: the job started. You see run times, and a run that passes the Maximum run time alerts.…/your-token/fail: the job failed. You are alerted right away instead of at the deadline.…/your-token/0to/255: the exit code. 0 is success, anything else a failure.
GET, POST and HEAD all work, and the answer is OK. A POST body is kept as the job’s output and shown with failures and in the alert. We read up to 64 kB and keep the first and last parts, 10,000 characters in all. A larger body is refused and the ping is lost, so send the end of the log, as below. The token in the URL is the secret, so keep it out of public logs.
A wrapper for any scheduler
This script runs a command, reports its start, its exit code and the last 60 kB of output, and passes the exit code on. Save it as /usr/local/bin/with-ping and run chmod +x on it.
#!/bin/sh
# with-ping URL COMMAND...: runs COMMAND and reports it to Uptimecheck
url="$1"; shift
curl -fsS -m 10 --retry 3 -o /dev/null "$url/start"
log=$(mktemp)
"$@" > "$log" 2>&1
code=$?
tail -c 60000 "$log" | curl -fsS -m 10 --retry 3 --data-binary @- -o /dev/null "$url/$code"
rm -f "$log"
exit $code
crontab
# Ping when the job succeeds
0 3 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 --retry 3 -o /dev/null https://app.uptimecheck.com/api/hb/your-token
# Or report start, exit code and output with the script above
0 3 * * * /usr/local/bin/with-ping https://app.uptimecheck.com/api/hb/your-token /usr/local/bin/backup.sh
Give the monitor the same schedule and the Time zone the crontab runs in, often UTC.
Laravel scheduler
Laravel pings URLs itself. In routes/console.php (Laravel 11 and later; before that, the same methods on $schedule in app/Console/Kernel.php):
use Illuminate\Support\Facades\Schedule;
Schedule::command("backup:run")
->dailyAt("03:00")
->pingBefore("https://app.uptimecheck.com/api/hb/your-token/start")
->pingOnSuccess("https://app.uptimecheck.com/api/hb/your-token")
->pingOnFailure("https://app.uptimecheck.com/api/hb/your-token/fail");
A failure is a command that ends with a non-zero exit code. The schedule follows the app’s time zone unless you add ->timezone(); set the same on the monitor.
Kubernetes CronJob
Store the ping URL as a secret with kubectl create secret generic uptimecheck --from-literal=ping-url=https://app.uptimecheck.com/api/hb/your-token. The image needs curl.
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-backup
spec:
schedule: "0 3 * * *"
timeZone: "Europe/Stockholm"
concurrencyPolicy: Forbid
jobTemplate:
spec:
backoffLimit: 0
template:
spec:
restartPolicy: Never
containers:
- name: backup
image: registry.example.com/backup:1.4
env:
- name: PING_URL
valueFrom:
secretKeyRef:
name: uptimecheck
key: ping-url
command: ["/bin/sh", "-c"]
args:
- |
curl -fsS -m 10 --retry 3 -o /dev/null "$PING_URL/start"
/app/backup.sh > /tmp/out.log 2>&1
code=$?
tail -c 60000 /tmp/out.log | curl -fsS -m 10 --retry 3 --data-binary @- -o /dev/null "$PING_URL/$code"
exit $code
If the pod never starts, for example because the image can’t be pulled, no ping arrives and the monitor alerts at the deadline. timeZone needs Kubernetes 1.27 or later.
GitHub Actions
on:
schedule:
- cron: "0 3 * * *"
jobs:
nightly:
runs-on: ubuntu-latest
env:
PING_URL: ${{ secrets.UPTIMECHECK_PING_URL }}
steps:
- uses: actions/checkout@v4
- run: curl -fsS -m 10 --retry 3 -o /dev/null "$PING_URL/start" || true
- run: ./scripts/nightly.sh
- if: success()
run: curl -fsS -m 10 --retry 3 -o /dev/null "$PING_URL"
- if: failure()
run: curl -fsS -m 10 --retry 3 -o /dev/null "$PING_URL/fail"
Save the ping URL as the repository secret UPTIMECHECK_PING_URL. Give the monitor the workflow’s time zone, UTC by default. GitHub can start scheduled runs late when it is busy, so allow a generous Grace period, such as 30 minutes.
systemd timer
# /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/with-ping https://app.uptimecheck.com/api/hb/your-token /usr/local/bin/backup.sh
# /etc/systemd/system/backup.timer
[Unit]
Description=Run the nightly backup
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
Turn it on with sudo systemctl daemon-reload and sudo systemctl enable --now backup.timer. OnCalendar follows the server’s time zone.
Windows Task Scheduler
# C:\Scripts\backup-with-ping.ps1
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$ping = "https://app.uptimecheck.com/api/hb/your-token"
try { Invoke-RestMethod -Uri "$ping/start" -TimeoutSec 10 | Out-Null } catch {}
$output = & "C:\Scripts\backup.cmd" 2>&1 | Out-String
$code = $LASTEXITCODE
if ($output.Length -gt 30000) { $output = $output.Substring($output.Length - 30000) }
Invoke-RestMethod -Uri "$ping/$code" -Method Post -Body $output -TimeoutSec 10 | Out-Null
exit $code
Register it to run every night at 03:00, in PowerShell as Administrator:
$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File C:\Scripts\backup-with-ping.ps1"
$trigger = New-ScheduledTaskTrigger -Daily -At 3am
Register-ScheduledTask -TaskName "Nightly backup" -Action $action -Trigger $trigger -User "SYSTEM" -RunLevel Highest
Task Scheduler uses the computer’s time zone; set the same on the monitor. Read more about cron expressions and cron job monitoring.