Get notified on your phone when a cron job fails
Cron job failure notification in 5 minutes: a bash wrapper that pushes to your iPhone the moment a cron task exits non-zero.
You set up a cron job. It runs nightly. Six weeks later you notice the backup script has been silently failing because tar ran out of disk space on day three. The MAILTO line at the top of crontab? You never set one up, and the server can't send mail anyway.
Here's a five-minute fix: a bash wrapper that pushes a notification to your iPhone the moment a cron task exits non-zero. No monitoring stack, no agent, no cloud dashboards — just one curl call per failure.
What you'll need
- A Linux or macOS box with cron (or any scheduler that runs shell commands)
curlinstalled (it already is)- A free TheNotificationApp account and one app key
That's it. No daemon to install, no inbound port to open.
Step 1 — Get an API key
Sign in with Apple on thenotification.app, install the iOS app, then create an app inside the dashboard. Copy the app_key it gives you. You can have three apps on the free tier (100 notifications total) and ten on Pro (1,000/month). See pricing for the full breakdown.
Step 2 — Drop in the wrapper
Create /usr/local/bin/notify-on-fail with this content:
#!/usr/bin/env bash
# Run a command. If it exits non-zero, push a notification.
# Usage: notify-on-fail <name> <command...>
APP_KEY="YOUR_API_KEY"
JOB_NAME="$1"
shift
# Capture stderr so we can include it in the notification body
LOG=$(mktemp)
"$@" 2> "$LOG"
EXIT_CODE=$?
if [ "$EXIT_CODE" -ne 0 ]; then
# Trim error to first 200 chars, escape quotes
ERR=$(head -c 200 "$LOG" | sed 's/"/\\"/g' | tr '\n' ' ')
HOST=$(hostname)
curl -s -X POST https://thenotification.app/api/sendNotification \
-H "app_key: $APP_KEY" \
-H "Content-Type: application/json" \
-d "{
\"title\": \"❌ $JOB_NAME failed on $HOST\",
\"body\": \"Exit $EXIT_CODE — $ERR\"
}"
fi
rm -f "$LOG"
exit $EXIT_CODE
Make it executable:
sudo chmod +x /usr/local/bin/notify-on-fail
The script preserves the original exit code at the end, so anything downstream (cron retry logic, parent scripts) still behaves correctly.
Step 3 — Update your crontab
Run crontab -e and prefix any job you care about with notify-on-fail:
# Old:
0 3 * * * /opt/scripts/backup.sh
# New:
0 3 * * * /usr/local/bin/notify-on-fail "nightly-backup" /opt/scripts/backup.sh
The first argument after the wrapper is a label — keep it short, it shows up as the notification title.
Step 4 — Force a failure and confirm
Don't wait until 3 a.m. to find out it works. Run a deliberately broken command from the shell:
/usr/local/bin/notify-on-fail "test-alert" false
Your phone should buzz within a second or two with:
❌ test-alert failed on yourhost
Exit 1 —
If nothing arrives, check that the iOS app is installed, the app key is correct, and the host can reach thenotification.app on port 443.
Optional — Get notified on success too
For jobs where silence is suspicious ("why hasn't the weekly report sent in three days?"), swap the conditional:
if [ "$EXIT_CODE" -eq 0 ]; then
curl -s -X POST https://thenotification.app/api/sendNotification \
-H "app_key: $APP_KEY" \
-H "Content-Type: application/json" \
-d "{\"title\": \"✅ $JOB_NAME ok\", \"body\": \"$(date)\"}"
fi
Optional — Add a link to the log
If you keep your cron logs behind a URL (Grafana, a static log viewer, anything), pass it through:
curl -s -X POST https://thenotification.app/api/sendNotification \
-H "app_key: $APP_KEY" \
-H "Content-Type: application/json" \
-d "{
\"title\": \"❌ $JOB_NAME failed on $HOST\",
\"body\": \"Exit $EXIT_CODE — tap to view log\",
\"link\": \"https://logs.example.com/$JOB_NAME\"
}"
Tapping the notification on your iPhone opens the URL directly.
Why a wrapper beats MAILTO
The classic cron failure pattern is MAILTO=you@example.com at the top of the crontab. Three problems:
- It only fires on stderr output, not non-zero exit codes — a script that fails silently still mails nothing
- You need a working
sendmailor relay configured on the host - Email is a poor signal channel for a thing that needs your attention right now
A push notification gives you a yes/no signal in the time it takes to glance at your watch, and the bash wrapper is honest about exit codes.
That's it
Five minutes of work and every cron job on the box now has a hard fail signal that reaches your pocket. No agent, no dashboard, no extra service running on the server.
If you want to dig deeper into the API — attaching images, dynamic links, or webhook-based variants — the curl docs have every option laid out. For a broader look at terminal-driven pushes (cron is one of many), see our walkthrough on sending iPhone push notifications with a single curl command.
Grab a free key at thenotification.app and your next failed cron will tell you itself.
Stop babysitting your scripts.
Free to download. Free tier available. Swiss-hosted, private by design.