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,/homeand data volumes too. - Use
hostname -sin the subject line so you can tell servers apart.