Monitor bash scripts: trap EXIT to ping on success or failure
Define a _finish function that checks $? and
either curls the success URL or POSTs to /fail,
then add trap '_finish' EXIT. Works with set -e:
any failing command exits the script, the trap fires, and the
exit-code check sends the right ping. Absence detection catches
SIGKILL and scripts that never start. Free, no monitor cap.
The snippets
Create a monitor in the console, set the schedule plus a grace window, copy the ping URL, and paste the trap header at the top of your script.
Minimal trap — exit code only
Works with any bash script. set -euo pipefail makes
every non-zero command exit immediately so the trap always fires on
the first error:
Capture stderr for the fail body
Without set -e, redirect stderr to a temp file.
If the script exits non-zero, POST the contents of that file to
/fail so the alert body contains the actual error
output — not just an exit code:
Optional: /start ping for overrun detection
A /start ping arms the hung-job alarm — if no success
ping arrives inside the grace window an incident opens even if the
script just hangs rather than crashing:
Why SIGKILL can't be trapped
trap catches EXIT, ERR,
TERM, and INT — but not
SIGKILL. An OOM-killed process sends no ping. That is
exactly what absence-detection handles: the missing ping itself
opens the incident after the grace window. See the
cron monitoring guide for the
scheduler side and the Python guide
for a language-level comparison. Also available:
LastPing MCP server for AI-agent provisioning.
What this catches
The trap reports what it can; the silence reports the rest.
- A failing command (set -e) — bash exits immediately on any non-zero command, the trap fires, and the exit code goes to
/fail. - A non-zero explicit exit —
exit 1triggers the EXIT trap; the body can include the captured stderr output. - SIGTERM — the EXIT trap fires on graceful shutdown signals, giving you a chance to report before the process ends.
- SIGKILL and OOM kills — untrapable; handled by absence detection: no ping reaches LastPing within the schedule+grace window → incident.
- The script never ran — missing cron entry, missing executable, dead host. Absence → incident.
Questions people ask
Front-loaded answers — the most important fact first.
-
Does trap EXIT work with set -e?
Yes.
set -eexits the script on any non-zero command; bash still runs the EXIT trap when the script exits, regardless of the cause. The$?inside the trap reflects the exit code that triggered the exit. -
Can I send the actual error message, not just the exit code?
Yes — redirect stderr to a temp file with
exec 2>$ERR_LOG(drop-efrom the shebang line so you control exits manually), then POST the file contents to/failusingcurl --data-binary @$ERR_LOG. Up to 10,000 bytes are stored with the ping event. -
What if the script is killed with SIGKILL?
SIGKILL cannot be caught — bash does not run EXIT handlers. Absence-detection monitoring handles this: the missing ping opens an incident after the grace window without any trap code running.
-
Is this free?
Yes. LastPing is free and fully hosted with no monitor cap and no paid tier. See how it compares to Healthchecks.io and Cronitor.
SIGKILL can't be trapped — absence detection is the safety net.
Five lines now beat a silent cron job later. First alert wired up in about a minute — and LastPing monitors itself the same way.