Scheduling disk space monitoring with cron

A simple threshold check for one host — and where it stops scaling once you have a fleet.

The problem

For a single machine, a cron job checking `df` output against a threshold is genuinely fine and low-effort. It stops being the right tool once you're managing more than a handful of machines: each host needs its own cron entry and alert path, there's no historical trend (just pass/fail at check time), and there's no single place to see which of twenty hosts is the one filling up.

The common scripting bug is matching the wrong filesystem line — `df -h` output includes tmpfs and overlay mounts that aren't meaningful to alert on, and a script that doesn't filter to real block devices will alert on a tmpfs that's "full" by design or miss the actual disk that matters.

Fine for one host via cron; use Prometheus/node_exporter (or similar) once you have a fleet.

A cron-based df check is a reasonable amount of engineering for a single server. Once you're managing several machines, a metrics/alerting stack (node_exporter + Prometheus + Alertmanager, or a hosted equivalent) gives you trends over time and one alerting path instead of N independent cron jobs that can each silently stop working.

Recommended schedule

*/30 * * * *

Every 30 minutes is frequent enough to catch a fast-filling disk (runaway logs, a stuck upload) well before it's critical, without being noisy.

Example crontab entry

# norc: disk-check Alert at 90% usage on /
*/30 * * * * /opt/scripts/disk-check.sh >> /var/log/disk-check.log 2>&1
#!/usr/bin/env bash
set -euo pipefail
usage=$(df -P / | awk 'NR==2 {gsub("%","",$5); print $5}')
[ "$usage" -ge 90 ] && /opt/scripts/alert.sh "disk at ${usage}% on $(hostname)"
exit 0

Failure modes to watch for

  • Matching a tmpfs/overlay mount instead of the real block device, alerting on noise or missing the actual full disk.
  • No hysteresis: a disk sitting at exactly 90% pages on every single check until it drops back below the threshold.
  • The alert path shares infrastructure with what fills the disk (e.g. alert log writes to the same volume that's full), so the last alert before the outage is the one that fails to send.
  • One cron job per host with no aggregation — at fleet scale, nobody notices host #14 stopped reporting at all.

How norc helps

norc gives one place to see this check's run history across every paired machine, so a script that's silently stopped running on one host is visible without SSHing in to check.