# Cron Job & Script Monitoring

> Monitor cron jobs and scripts: send success or failure notifications from crontab with curl, a reusable bash wrapper, and failure-only alerts.

Source: https://docs.alphorn.dev/use-cases/cron-jobs/

Cron jobs and batch scripts run silently. When they fail, nobody notices until something breaks downstream. Wrap your scripts with a notification call and route results through Alphorn.

## Basic pattern

Send a notification at the end of any script based on its exit code:

```bash
#!/bin/bash
WEBHOOK="https://app.alphorn.dev/n/V1StGXR8_Z5jdHi6B-myT"
ALPHORN_API_KEY="${ALPHORN_API_KEY:-alp_...}"  # or export it in the environment
JOB_NAME="nightly-data-sync"

# Your actual work
/usr/local/bin/sync-data.sh
EXIT_CODE=$?

if [ $EXIT_CODE -eq 0 ]; then
  curl -fsS -X POST "$WEBHOOK" \
    -H "Authorization: Bearer $ALPHORN_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{
      \"title\": \"$JOB_NAME completed\",
      \"message\": \"Job finished successfully\",
      \"priority\": 2,
      \"tags\": [\"cron\", \"success\"]
    }"
else
  curl -fsS -X POST "$WEBHOOK" \
    -H "Authorization: Bearer $ALPHORN_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{
      \"title\": \"$JOB_NAME FAILED\",
      \"message\": \"Job exited with code $EXIT_CODE\",
      \"priority\": 5,
      \"tags\": [\"cron\", \"failure\"]
    }"
fi
```

## Reusable wrapper

Create a generic notification wrapper you can use with any command (it builds the JSON with `jq`, so install that first):

```bash title="notify-run.sh"
#!/bin/bash
WEBHOOK="https://app.alphorn.dev/n/V1StGXR8_Z5jdHi6B-myT"
ALPHORN_API_KEY="${ALPHORN_API_KEY:-alp_...}"  # or export it in the environment
JOB_NAME="${1:-unknown-job}"
shift

# Run the command
"$@"
EXIT_CODE=$?

if [ $EXIT_CODE -eq 0 ]; then
  PRIORITY=2; STATUS="completed"; TAG="success"
else
  PRIORITY=5; STATUS="FAILED (exit $EXIT_CODE)"; TAG="failure"
fi

# -o /dev/null keeps curl's response out of the command's redirected stdout
jq -n --arg t "$JOB_NAME $STATUS" --arg m "Command: $*" --argjson p "$PRIORITY" --arg tag "$TAG" \
  '{title: $t, message: $m, priority: $p, tags: ["cron", $tag]}' |
curl -fsS -o /dev/null -X POST "$WEBHOOK" \
  -H "Authorization: Bearer $ALPHORN_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @-

exit $EXIT_CODE
```

Usage:

```bash
# In crontab
0 2 * * * /path/to/notify-run.sh "db-backup" pg_dump -U app mydb > /backups/nightly.sql
0 4 * * * /path/to/notify-run.sh "log-rotation" /usr/sbin/logrotate /etc/logrotate.conf
```

Cron doesn't load your shell profile, so a key exported in `~/.bashrc` isn't visible to these jobs. Either set it in the script (replace `alp_...`) or add a line like `ALPHORN_API_KEY=alp_...` at the top of the crontab (`crontab -e`), which cron passes to every job.

## Only notify on failure

If you don't want noise from successful runs, just skip the success notification - or use filtering rules in Alphorn to only route `failure` tagged messages to noisy channels like Slack, while sending everything to Email for audit.

## Routing examples

| Channel | Filter | Purpose |
|---|---|---|
| Slack (#ops) | Tags has any of `failure` | Only failures |
| Email | Tags has any of `cron` | Full log of all job runs |
| PagerDuty | Priority greater than 3 and tags has any of `failure` | Wake someone up for critical job failures |
