# Monitor server load, disk, CPU and memory with email alerts

A small shell script, run from cron every 5 minutes, that checks four health numbers and emails you when one goes over its limit. It doesn't need an agent or a monitoring server.

## What it checks
| Check | How it is read | Default limit |
|---|---|---|
| 1-minute load average | `/proc/loadavg` | 10.00 |
| CPU use | `vmstat 1 2` (100 minus idle) | 98 % |
| Root disk use | `df --output=pcent /` | 98 % |
| Memory use | `free` (used ÷ total) | 98 % |

Each limit can be overridden with an environment variable, so one script works on small and large machines:
```
LOAD_THRESHOLD=4 DISK_THRESHOLD=90 RECIPIENTS="you@example.com" /usr/local/bin/loadmon.sh
```

## Requirements
`awk`, `df`, `free`, `vmstat` (procps), `bc`, `logger`, a `mail` command (s-nail) with a working mail relay, and optionally `sar` (sysstat) to include recent history in the alert email.

Check for every tool at start-up, including `bc`, so a missing tool fails loudly instead of silently skipping alerts:
```
for c in awk df free vmstat bc mail logger; do
  command -v "$c" >/dev/null || { logger -t loadmon "missing $c"; exit 1; }
done
```

## Reading the numbers
```
load=$(cut -d' ' -f1 /proc/loadavg)
cpu=$(vmstat 1 2 | awk 'END {print 100 - $15}')
disk=$(df --output=pcent / | tail -1 | tr -dc '0-9')
mem=$(free | awk '/^Mem:/ {printf "%d", $3 * 100 / $2}')
if (( $(echo "$load > $LOAD_THRESHOLD" | bc -l) )); then ... fi
```
Avoid parsing `top -bn1` for CPU. Its first frame is an average since boot, and its column positions shift.

## Schedule it
`/etc/cron.d/loadmon`:
```
*/5 * * * * root /usr/local/bin/loadmon.sh >/dev/null 2>&1
```

## Tips
- **Throttle alerts.** Write a timestamp file per check (for example `/var/lib/loadmon/disk.last`), and only email again after an hour. Otherwise a full disk sends 12 emails an hour.
- **Rotate the log.** One line every 5 minutes is about 100,000 lines a year. Add `/etc/logrotate.d/loadmon`.
- **Check more than `/`.** Loop over `/var`, `/home` and data volumes too.
- Use `hostname -s` in the subject line so you can tell servers apart.
