Skip to content
Back to Blog
Linux & Server8 min read

Check Disk Usage Linux Best Practices That Work (2026)

Production servers need real-time disk monitoring, not just df -h once a week. Here's what actually prevents outages.

Written by Abdul AbrorTechnical Hosting Support Engineer
Check Disk Usage Linux Best Practices That Work (2026)
On this page

I've seen more production outages from full disks than from almost any other infrastructure failure. A web server runs out of space, logs stop writing, databases lock up, and suddenly you're explaining to a client why their checkout page returned a 500 for two hours.

The fix is never just running df -h when things break. You need automated monitoring, the right tools for different scenarios, and a baseline understanding of what normal looks like for your workload.

Why df alone isn't enough

Most engineers reach for df -h first. It's fast, it's built-in, and it shows partition usage at a glance:

df -h

But df only tells you how full each filesystem is right now. It won't show you what is filling the disk, which directory tree is growing, or whether inodes are exhausted even though you still have free space. I've debugged servers where df reported 40% usage but the partition was functionally full because every inode was allocated.

Check inode usage separately:

df -i

If you see 100% inode usage, you have too many small files—often session data, cache fragments, or mail queue files. The solution is different from a space problem.

What you should actually use

du for directory-level investigation

When a partition fills up, du locates the culprit. Start at the root of the problem filesystem:

du -sh /* 2>/dev/null | sort -rh | head -n 10

This shows the ten largest top-level directories in human-readable sizes, sorted descending. The 2>/dev/null hides permission errors you'll hit scanning /proc or /sys.

Once you identify the big directory, drill down:

du -sh /var/* 2>/dev/null | sort -rh | head -n 10

In my experience, /var/log and /var/lib/mysql account for most unexpected growth on hosting servers. Sometimes it's a single 80GB error log from a misconfigured PHP app.

ncdu for interactive exploration

When you need to navigate the filesystem visually, ncdu beats du by miles. Install it first:

# Debian/Ubuntu
apt install ncdu

# RHEL/Rocky/AlmaLinux
dnf install ncdu

Then run it on the partition:

ncdu /var

You get a navigable tree view sorted by size. Arrow keys move around, d deletes files directly (careful), and q quits. It's especially useful when you're hunting through nested subdirectories and need to see context.

Patterns that catch you off guard

Deleted files still holding space

A process can keep a file descriptor open even after the file is deleted. The space won't free until the process closes the handle or restarts. This trips up people constantly.

Find them with lsof:

lsof +L1

The +L1 flag shows files with a link count less than 1—deleted but still open. You'll see the process ID and the file path (marked as (deleted)).

Restart the offending service, or kill the process if it's safe. The space returns immediately.

Log rotation misconfiguration

Logrotate is supposed to keep /var/log under control. But if a service holds its log file open and logrotate only renames the file without signaling the process to reopen, logs continue writing to the renamed (often compressed) file and break everything.

Check your logrotate config for the relevant service:

cat /etc/logrotate.d/nginx

You want a postrotate block that reloads the daemon:

/var/log/nginx/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    postrotate
        systemctl reload nginx > /dev/null 2>&1 || true
    endscript
}

The delaycompress is key—it waits one rotation cycle before compressing, giving the service time to finish writing to the old file.

Temporary files in /tmp or /var/tmp

Applications create temporary files and crash before cleanup. Over months, /tmp accumulates gigabytes. Modern distros usually mount /tmp as tmpfs (RAM-backed), but /var/tmp persists across reboots and follows the same filesystem as /var.

Set up a daily cron job to purge old temp files:

find /var/tmp -type f -atime +7 -delete

This deletes files not accessed in seven days. Adjust the threshold to match your workload.

How to automate monitoring

Manual checks don't scale. What works is threshold-based alerting tied to your existing monitoring stack.

Disk usage alerts in Prometheus

If you run Prometheus and node_exporter, add an alert rule for filesystem usage:

groups:
  - name: disk
    interval: 60s
    rules:
      - alert: DiskSpaceWarning
        expr: (
          node_filesystem_avail_bytes{mountpoint="/"}
          / node_filesystem_size_bytes{mountpoint="/"}
        ) < 0.2
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Disk space below 20% on {{ $labels.instance }}"

This triggers when the root filesystem drops below 20% free for five consecutive minutes. Adjust the mountpoint and threshold for each critical partition.

Simple shell script for smaller setups

No Prometheus? A cron job with a bash script does the job:

#!/bin/bash
THRESHOLD=85
EMAIL="[email protected]"

df -H | grep -vE '^Filesystem|tmpfs|cdrom' | awk '{ print $5 " " $1 }' | while read output;
do
  usage=$(echo $output | awk '{ print $1}' | sed 's/%//g')
  partition=$(echo $output | awk '{ print $2 }')
  if [ $usage -ge $THRESHOLD ]; then
    echo "ALERT: $partition is ${usage}% full" | mail -s "Disk Alert: $(hostname)" $EMAIL
  fi
done

Drop it in /etc/cron.hourly/disk-check and make it executable. You'll get an email when any partition crosses 85%.

Anti-patterns that make things worse

Running du on the entire root filesystem in production

Running du -sh / during peak hours hammers the disk I/O and slows everything else down. The filesystem cache gets evicted, database queries slow, and users notice.

Always scope du to a specific subtree. If you must scan everything, use ionice to lower the priority:

ionice -c3 du -sh /var

Class 3 is idle priority—it only runs when no other I/O is waiting.

Ignoring inode exhaustion

You can have 50GB free and still be unable to create files. Check inodes first when df looks fine but writes fail with "No space left on device."

Maildir setups and session storage are common causes. Each email or session is a separate file. Thousands of tiny files eat inodes fast.

Not monitoring growth rate

Knowing a partition is 60% full today means nothing without context. Is it growing 1% per day or 10%?

Track usage over time. Most monitoring systems graph this automatically, but even a weekly cron job logging df output to a CSV gives you trend data:

date +"%Y-%m-%d %H:%M" >> /var/log/disk-usage.log
df -h >> /var/log/disk-usage.log

Plot it monthly. You'll see seasonal patterns (backup schedules, log volume spikes) and catch runaway growth before it becomes an emergency.

What happens when you're already at 100%

Panic doesn't help. Here's the checklist.

  1. Identify the largest files immediately: bash find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null This lists every file over 100MB. You'll spot the log file or database dump that exploded overnight.

  2. Check for deleted-but-open files: bash lsof +L1 | grep deleted Restart the services holding those descriptors.

  3. Clear old logs manually: ```bash

    /var/log/huge-logfile.log `` The>` truncates the file in place without unlinking it, so open file descriptors still work.

  4. Remove old package caches: ```bash # Debian/Ubuntu apt-get clean

# RHEL/Rocky dnf clean all ```

  1. Purge old kernels (if you're on a system that doesn't auto-clean): bash # Debian/Ubuntu apt autoremove --purge

Once you have breathing room, figure out what caused the spike and fix the root cause—usually log rotation, backup retention, or a runaway process.

What to check first

When disk issues hit production, speed matters. Check df -h and df -i together—you need both space and inode counts. Run lsof +L1 to catch deleted files still holding space, then use du or ncdu to locate the largest directories.

Automate this before the next outage. A five-minute monitoring setup beats an hour of emergency firefighting at 2 AM. Set alerts at 80%, watch growth trends weekly, and keep log rotation configs tight.

The tools are simple. What separates working systems from broken ones is using them before you have to.

FAQ

What's the difference between df and du?

df reports filesystem-level usage from the kernel's perspective—how much space is allocated. du walks the directory tree and sums file sizes. They can disagree when files are deleted but still open, or when sparse files are involved.

How do I check disk usage for a specific user?

Run du on their home directory: du -sh /home/username. For system-wide file ownership, use find / -user username -exec du -ch {} + 2>/dev/null | tail -n 1, though it's slow on large filesystems.

Why does df show less free space than du suggests?

Filesystems reserve a percentage of space for root (usually 5%). Also, filesystem metadata (inodes, journals) consumes space that du doesn't count. Check reserved blocks with tune2fs -l /dev/sda1 | grep "Reserved block count".

Can I safely delete everything in /var/log?

No. Truncate active logs with > logfile instead of rm, so services don't break. Archive or compress older rotated logs first. Some logs (like auth.log or syslog) are needed for security audits.

What's a safe disk usage threshold for alerts?

I set warnings at 80% and critical alerts at 90%. Below 80%, filesystems perform normally. Above 90%, fragmentation increases and some applications start failing unpredictably. Adjust based on how fast your disks fill.