Automating Disk Space Checks with df and Shell Scripts
Keeping disk usage under control prevents service failures, data loss, and degraded performance. This guide shows a practical, automatable approach using the df command and simple shell scripts to monitor disk space, send alerts, and take basic remedial actions.
What you’ll build
- A portable shell script that:
- Checks filesystem usage with df.
- Alerts when usage exceeds configurable thresholds.
- Optionally cleans temporary files or rotates logs.
- Can be run manually or scheduled via cron/systemd timer.
Assumptions and defaults
- POSIX‑compatible shell (bash/sh).
- Linux systems where df supports human-readable and percent output.
- Default threshold: 85% usage triggers alerts.
- Alert method: console output and email via mailx (optional). Replace with your favorite notifier.
Script: disk-check.sh
bash
#!/usr/bin/env bash # disk-check.sh — simple disk usage monitor # Usage: disk-check.sh [threshold_percent] [email_address] THRESHOLD=\({1</span><span class="token" style="color: rgb(57, 58, 52);">:-</span><span class="token" style="color: rgb(54, 172, 170);">85}</span><span> </span><span></span><span class="token assign-left" style="color: rgb(54, 172, 170);">ALERT_EMAIL</span><span class="token" style="color: rgb(57, 58, 52);">=</span><span class="token" style="color: rgb(54, 172, 170);">\){2:-} # Filesystems to ignore (pattern list) IGNORE_FS_REGEX=”^tmpfs|^devtmpfs|^overlay|^squashfs” # Get df output (exclude header), show percent and mount # Example line: /dev/sda150G 40G 10G 80% / df -P -h | awk ‘NR>1{print \(1,\)5,\(6}'</span><span> </span><span class="token" style="color: rgb(57, 58, 52);">|</span><span> </span><span class="token" style="color: rgb(0, 0, 255);">while</span><span> </span><span class="token builtin" style="color: rgb(43, 145, 175);">read</span><span> -r fs pct </span><span class="token" style="color: rgb(57, 58, 52);">mount</span><span class="token" style="color: rgb(57, 58, 52);">;</span><span> </span><span class="token" style="color: rgb(0, 0, 255);">do</span><span> </span><span> </span><span class="token" style="color: rgb(0, 128, 0); font-style: italic;"># skip pseudo filesystems</span><span> </span><span> </span><span class="token" style="color: rgb(0, 0, 255);">if</span><span> </span><span class="token" style="color: rgb(57, 58, 52);">[</span><span class="token" style="color: rgb(57, 58, 52);">[</span><span> </span><span class="token" style="color: rgb(54, 172, 170);">\)fs =~ \(IGNORE_FS_REGEX</span><span> </span><span class="token" style="color: rgb(57, 58, 52);">]</span><span class="token" style="color: rgb(57, 58, 52);">]</span><span class="token" style="color: rgb(57, 58, 52);">;</span><span> </span><span class="token" style="color: rgb(0, 0, 255);">then</span><span> </span><span> </span><span class="token builtin" style="color: rgb(43, 145, 175);">continue</span><span> </span><span> </span><span class="token" style="color: rgb(0, 0, 255);">fi</span><span> </span> <span> </span><span class="token" style="color: rgb(0, 128, 0); font-style: italic;"># strip % sign</span><span> </span><span> </span><span class="token assign-left" style="color: rgb(54, 172, 170);">used</span><span class="token" style="color: rgb(57, 58, 52);">=</span><span class="token" style="color: rgb(54, 172, 170);">\){pct%%} if (( used >= THRESHOLD )); then msg=“ALERT: \(mount</span><span class="token" style="color: rgb(163, 21, 21);"> (</span><span class="token" style="color: rgb(54, 172, 170);">\)fs) is at \({used}</span><span class="token" style="color: rgb(163, 21, 21);">% (threshold </span><span class="token" style="color: rgb(54, 172, 170);">\){THRESHOLD}%)” echo “\(msg</span><span class="token" style="color: rgb(163, 21, 21);">"</span><span> </span><span> </span><span class="token" style="color: rgb(0, 128, 0); font-style: italic;"># send email if configured</span><span> </span><span> </span><span class="token" style="color: rgb(0, 0, 255);">if</span><span> </span><span class="token" style="color: rgb(57, 58, 52);">[</span><span> -n </span><span class="token" style="color: rgb(163, 21, 21);">"</span><span class="token" style="color: rgb(54, 172, 170);">\)ALERT_EMAIL” ]; then printf ”%s Full df -h output: “ ”\(msg</span><span class="token" style="color: rgb(163, 21, 21);">"</span><span> </span><span class="token" style="color: rgb(57, 58, 52);">|</span><span> </span><span class="token" style="color: rgb(57, 58, 52);">cat</span><span> - </span><span class="token" style="color: rgb(57, 58, 52);"><</span><span class="token" style="color: rgb(57, 58, 52);">(</span><span class="token" style="color: rgb(57, 58, 52);">df</span><span> -h</span><span class="token" style="color: rgb(57, 58, 52);">)</span><span> </span><span class="token" style="color: rgb(57, 58, 52);">|</span><span> mailx -s </span><span class="token" style="color: rgb(163, 21, 21);">"Disk space alert: </span><span class="token" style="color: rgb(54, 172, 170);">\)mount at \({used}</span><span class="token" style="color: rgb(163, 21, 21);">%"</span><span> </span><span class="token" style="color: rgb(163, 21, 21);">"</span><span class="token" style="color: rgb(54, 172, 170);">\)ALERTEMAIL“ fi # optional automated action: rotate logs or clean cache # example: delete files older than 30 days in /var/log/myapp (customize) # find /var/log/myapp -type f -mtime +30 -delete fi done
How it works (brief)
- df -P -h prints portable, human-readable output.
- awk extracts device, usage percent, and mount point.
- Script ignores pseudo filesystems like tmpfs.
- Alerts when usage >= threshold and optionally emails the admin.
- Customize the automated action section for safe, environment-specific cleanup.
Scheduling with cron
Edit root’s crontab (or a service account) to run every 15 minutes:
- Run crontab -e and add:
cron
*/15 * * * * /usr/local/bin/disk-check.sh 85 [email protected] >/dev/null 2>&1
Scheduling with systemd timer (alternative)
Create /etc/systemd/system/disk-check.service:
ini
[Unit] Description=Disk space check [Service] Type=oneshot ExecStart=/usr/local/bin/disk-check.sh 85 [email protected]
Create /etc/systemd/system/disk-check.timer:
ini
[Unit] Description=Run disk-check every 15 minutes [Timer] OnBootSec=5min OnUnitActiveSec=15min [Install] WantedBy=timers.target
Enable and start:
- systemctl daemon-reload
- systemctl enable –now disk-check.timer
Enhancements and safety tips
- Use df -B1 for byte-precise checks in scripts requiring exact thresholds.
- Add logging to syslog or a file for auditability.
- Avoid destructive automated cleanup unless fully tested; prefer alerting first.
- Consider using inotify-based or dedicated monitoring (Prometheus nodeexporter + alertmanager) for large environments.
Example: byte-precise check snippet
bash
# compare used bytes to threshold bytes for mount avail_bytes=\((</span><span class="token" style="color: rgb(57, 58, 52);">df</span><span class="token" style="color: rgb(54, 172, 170);"> --output</span><span class="token" style="color: rgb(57, 58, 52);">=</span><span class="token" style="color: rgb(54, 172, 170);">avail -B1 </span><span class="token" style="color: rgb(163, 21, 21);">"</span><span class="token" style="color: rgb(163, 21, 21);">\)mount“ | tail -n1) size_bytes=\((</span><span class="token" style="color: rgb(57, 58, 52);">df</span><span class="token" style="color: rgb(54, 172, 170);"> --output</span><span class="token" style="color: rgb(57, 58, 52);">=</span><span class="token" style="color: rgb(54, 172, 170);">size -B1 </span><span class="token" style="color: rgb(163, 21, 21);">"</span><span class="token" style="color: rgb(163, 21, 21);">\)mount” | tail -n1) used_bytes=\(((</span><span class="token" style="color: rgb(54, 172, 170);"> size_bytes </span><span class="token" style="color: rgb(57, 58, 52);">-</span><span class="token" style="color: rgb(54, 172, 170);"> avail_bytes </span><span class="token" style="color: rgb(54, 172, 170);">))</span><span> </span><span></span><span class="token assign-left" style="color: rgb(54, 172, 170);">threshold_bytes</span><span class="token" style="color: rgb(57, 58, 52);">=</span><span class="token" style="color: rgb(54, 172, 170);">\)(( size_bytes * THRESHOLD / 100 )) if (( used_bytes >= threshold_bytes )); then # alert fi
Quick checklist before deploying
- Test the script manually on non-production mounts.
- Configure accurate ignore patterns for ephemeral filesystems.
- Verify email delivery or other alert channels.
- Start with notifications only; add automated cleanup after monitoring behavior for a period.
This script is a minimal, flexible starting point—customize mount ignores, alerting, and remediation steps to match your environment.
Leave a Reply