Monitor Bash Scripts with Crontiq
Bash scripts called from crontab are the most common form of scheduled automation on Linux servers. They are also the most fragile. A missing binary, a full disk, a changed PATH — any of these can break your script silently. Crontab sends failure output to local mail that nobody reads. If the script never runs at all, there is nothing to report.
Crontiq monitors your bash cron jobs with a single curl command. If the curl does not arrive on time, you get an email alert. If you send JSON metrics, Crontiq detects anomalies automatically.
Simplest Integration: One Curl
Add one line at the end of your script. If the script fails before reaching it, Crontiq detects the missing ping.
#!/bin/bash
# backup_db.sh — Nightly PostgreSQL backup
set -euo pipefail
BACKUP_FILE="/backups/db-$(date +%Y%m%d).sql.gz"
pg_dump mydb | gzip > "$BACKUP_FILE"
# Ping Crontiq on success
curl -fsS -o /dev/null \
https://ping.crontiq.io/p/cq_live_80381902d7b36613/db-backup
The set -e flag ensures the script exits on any error, so the curl never runs if the backup fails. The monitor db-backup is auto-created on the first ping.
Trap Failures with ERR
For explicit failure reporting, use bash's trap to call the /fail endpoint when any command fails. This gives you immediate notification rather than waiting for the timeout.
#!/bin/bash
# sync_files.sh — Sync files to remote storage
set -euo pipefail
CRONTIQ="https://ping.crontiq.io/p/${CRONTIQ_API_KEY}/file-sync"
# Report failure on any error
trap 'curl -fsS -o /dev/null "${CRONTIQ}/fail"' ERR
# Signal start
curl -fsS -o /dev/null "${CRONTIQ}/start"
# Your actual work
rsync -az --delete /data/files/ remote:/backups/files/
# Report success
curl -fsS -o /dev/null "$CRONTIQ"
The trap catches any non-zero exit code and pings the /fail endpoint before the script terminates. This means you get alerted within seconds of a failure, not after a timeout window.
Send Metrics with jq
Use jq to build a JSON payload with metrics from your script. Crontiq extracts every numeric value and tracks it over time.
#!/bin/bash
# cleanup_logs.sh — Remove old log files and report metrics
set -euo pipefail
CRONTIQ="https://ping.crontiq.io/p/${CRONTIQ_API_KEY}/log-cleanup"
START_TIME=$(date +%s%3N)
trap 'curl -fsS -o /dev/null "${CRONTIQ}/fail"' ERR
curl -fsS -o /dev/null "${CRONTIQ}/start"
# Count files before cleanup
TOTAL_BEFORE=$(find /var/log/app -name "*.log" -mtime +30 | wc -l)
# Get disk usage before
DISK_BEFORE=$(df /var/log --output=used | tail -1 | tr -d ' ')
# Delete old logs
find /var/log/app -name "*.log" -mtime +30 -delete
# Get disk usage after
DISK_AFTER=$(df /var/log --output=used | tail -1 | tr -d ' ')
FREED_MB=$(( (DISK_BEFORE - DISK_AFTER) / 1024 ))
END_TIME=$(date +%s%3N)
DURATION=$(( END_TIME - START_TIME ))
# Build and send JSON metrics
jq -n \
--argjson files "$TOTAL_BEFORE" \
--argjson freed "$FREED_MB" \
--argjson duration "$DURATION" \
'{files_deleted: $files, disk_freed_mb: $freed, duration_ms: $duration}' | \
curl -fsS -o /dev/null -X POST \
-H "Content-Type: application/json" \
-d @- \
"$CRONTIQ"
Crontiq receives the JSON and automatically tracks files_deleted, disk_freed_mb, and duration_ms. If the number of deleted files drops to zero (maybe the find path changed), Crontiq flags a WARNING.
Using Exit Codes
Crontiq supports exit code reporting. Append the exit code to the URL: 0 means success, anything else means failure.
#!/bin/bash
# run_tests.sh — Run test suite and report result
set -uo pipefail
CRONTIQ="https://ping.crontiq.io/p/${CRONTIQ_API_KEY}/test-suite"
/opt/app/run_tests.sh
EXIT_CODE=$?
# Report exit code directly
curl -fsS -o /dev/null "${CRONTIQ}/${EXIT_CODE}"
exit $EXIT_CODE
Crontab Entry Examples
Set your API key once in the crontab environment, then reference it in all entries.
# crontab -e
CRONTIQ_API_KEY=cq_live_80381902d7b36613
# Nightly backup at 02:00
0 2 * * * /opt/scripts/backup_db.sh 2>>/var/log/backup.log
# Hourly file sync
0 * * * * /opt/scripts/sync_files.sh 2>>/var/log/sync.log
# Daily cleanup at 04:30
30 4 * * * /opt/scripts/cleanup_logs.sh 2>>/var/log/cleanup.log
# Quick one-liner: backup + ping
0 3 * * * pg_dump mydb | gzip > /backups/db.sql.gz && curl -fsS -o /dev/null https://ping.crontiq.io/p/${CRONTIQ_API_KEY}/quick-backup
Why Curl to Crontiq Beats Local Monitoring
- If the server is down, local monitoring is down too. Crontiq runs externally and detects the missing ping.
- Crontab's
MAILTO relies on a local MTA that is often misconfigured or not installed.
- A script that is removed from crontab produces no logs. Crontiq detects the absence.
- Crontiq gives you historical trends, anomaly detection, and a public status badge — all from a single curl.