Automation projects
Build a health checker
Check an HTTP endpoint, capture timing and status, and return a useful result for a scheduler or monitor.
10 minute lesson
A health checker answers one question on a schedule: is the service actually working? “The process is running” is not that answer, and neither is “the server returned something.” A health checker needs a deadline and a small expected contract. It should not accept every HTTP response as success.
Check one page
#!/usr/bin/env bash
if curl --fail --silent --show-error --max-time 5 https://example.org/ | grep -q 'Example Domain'; then
printf '%s\n' 'healthy'
else
printf '%s\n' 'unhealthy' >&2
exit 1
fi
Each flag carries policy. --fail makes curl exit non-zero on HTTP errors like 500 — without it, a pretty error page counts as a successful transfer. --max-time 5 is the deadline: a hanging service must become a fast failure, not an eternal wait. --silent --show-error drops the progress noise but keeps real error messages.
The grep -q 'Example Domain' part is the contract: the page must contain text the working service is known to render. A load balancer serving a blank 200 page fails the check, exactly as it should. -q suppresses grep’s output because only its exit status matters here.
Verify each failure boundary
Break DNS, the expected text, and the timeout. Each fault should fail through a recognizable boundary:
curl --fail --silent --show-error --max-time 5 https://nonexistent.example.invalid/
# curl: (6) Could not resolve host: nonexistent.example.invalid
# now change the grep pattern to text that isn't on the page:
./health-check
# unhealthy
Also confirm echo $? prints 1 on every failure path. The exit status is what makes this script composable: cron, systemd, and monitoring agents branch on the number, not the words. A checker that prints unhealthy but exits zero reports success to every machine reading it.
Keep the checker itself safe
Avoid logging response bodies containing private data. A health endpoint that echoes user records into a monitoring log turns a probe into a leak — log the outcome and the status code, not the payload.
If the checker must authenticate, monitoring credentials need narrow read-only scope. A token that can only call the health endpoint is boring to steal; reusing an admin token in a script that runs every minute is not.
Lesson completed