Server Disk Space Management: Finding What’s Eating Your Storage

Disk space has a way of filling up at the worst possible time. I’ve had databases refuse to write because /var was full, deployments fail because /tmp was full, and applications crash because their log directories hit quota. All of them were preventable with basic disk space management.

Here’s how I handle it.

Finding Large Files and Directories

When disk space is low, the first thing I do is find what’s taking up space:

# How full is each partition?
df -h

# How much space does each directory use?
du -sh /* 2>/dev/null | sort -h

# Top 20 largest directories under /var
du -h /var --max-depth=3 2>/dev/null | sort -rh | head -20

# Top 20 largest files in /var/log
find /var/log -type f -printf '%s %p\n' 2>/dev/null | sort -rn | head -20

du -sh /* is the quick way to identify which top-level directory is the problem. Then drill down from there.

For an interactive visual tool, ncdu is excellent:

apt install ncdu
ncdu /var

ncdu shows a navigable tree of disk usage. Much faster for manual investigation than running du repeatedly.

What’s Usually Taking Up Space

In my experience, the culprits are almost always one of:

Log files — applications generating more logs than expected, log rotation misconfigured, or log rotation not configured at all. Check /var/log/ first.

Package manager cache — old .deb or .rpm packages accumulate.

# Debian/Ubuntu
apt clean
apt autoremove

# CentOS/RHEL
dnf clean all
dnf autoremove

Old kernel images — Linux distributions often keep several old kernels:

dpkg --list | grep linux-image    # List installed kernels
apt autoremove                     # Usually removes old kernels safely

Docker — container images, stopped containers, unused volumes:

docker system df      # Show Docker disk usage
docker system prune   # Remove all unused resources (careful — asks confirmation)
docker image prune    # Remove unused images only
docker volume prune   # Remove unused volumes

Application temporary files — uploads directories, cache directories, temporary processing files.

Database data files — if a table or database grew unexpectedly.

Log Management

Logs are the most common cause of disk space issues on production servers. The solution is logrotate with appropriate retention settings.

Quick remediation when disk is full:

# Check large log files
find /var/log -name "*.log" -size +100M 2>/dev/null

# Safely truncate a large log file (don't delete — the application may have it open)
> /var/log/myapp/huge.log     # Empties the file while preserving the file descriptor

# Force log rotation immediately
logrotate --force /etc/logrotate.d/myapp

Don’t delete log files that running processes have open. Truncate them instead (> filename). Deleting a file that’s open doesn’t free the disk space — the space isn’t freed until the process closes the file descriptor.

Check if a process has a deleted-but-open file:

lsof +L1 | grep deleted

+L1 shows files with a link count less than 1 — meaning they’ve been deleted from the filesystem but are still open. If you see your log file here, restart the application to free the space.

Monitoring Disk Space

Set up alerts before disks fill up, not after.

Simple bash script for disk monitoring:

#!/bin/bash
THRESHOLD=85
MAILTO="you@example.com"

while read line; do
    usage=$(echo "$line" | awk '{ print $5 }' | tr -d '%')
    mount=$(echo "$line" | awk '{ print $6 }')

    if [ "$usage" -gt "$THRESHOLD" ]; then
        echo "Disk space warning: $mount is ${usage}% full" | \
          mail -s "Disk space warning on $(hostname)" "$MAILTO"
    fi
done < <(df -h | grep -E '^/dev')

Run this via cron every hour:

0 * * * * /usr/local/bin/disk-monitor.sh

For better monitoring, Netdata and similar tools alert on disk usage automatically and don’t require custom scripts.

Setting Disk Quotas

On shared servers, disk quotas prevent one user or process from filling the disk:

apt install quota

Enable quotas for a partition in /etc/fstab:

/dev/sda1    /home    ext4    defaults,usrquota,grpquota    0 1

Remount and initialize:

mount -o remount /home
quotacheck -cug /home
quotaon /home

Set quota for a user:

edquota -u username

This opens an editor showing block and inode limits. Set soft and hard limits:

Disk quotas for user username (uid 1001):
  Filesystem  blocks  soft  hard  inodes  soft  hard
  /dev/sda1   1048576  2097152  4194304  0  0  0

Blocks are in KB. The example gives a 2GB soft limit and 4GB hard limit.

Check quota usage:

repquota /home
quota -u username

LVM-Based Solutions

If a partition is too small and you can’t just delete things, LVM makes adding storage easy:

# Extend an LVM volume when you add a new disk (see LVM guide)
lvextend -L +20G --resizefs /dev/vg0/data

Without LVM, you’d need to resize the partition, which often requires unmounting and rebooting. With LVM it’s done live in a few seconds.

For new servers, I always use LVM. The flexibility is worth the small overhead.

Cleaning Up Old Files Automatically

Find and delete files older than 30 days in a temp directory:

find /tmp -type f -mtime +30 -delete
find /var/tmp -type f -mtime +30 -delete

Add to cron:

0 4 * * * find /tmp -type f -mtime +30 -delete 2>/dev/null
0 4 * * * find /var/cache/myapp -type f -mtime +7 -delete 2>/dev/null

Be careful with find -delete — there’s no confirmation. Test with find -print first to see what would be deleted.

Inodes

Inodes are separate from disk space. A partition can run out of inodes even when there’s still free space. This happens when there are millions of tiny files:

df -i    # Show inode usage per filesystem

If inode usage is at 100%, you can’t create new files even if there’s disk space available. The error message is often confusing — “no space left on device” when df -h shows 40% free.

Check for directories with huge numbers of small files:

find /var -type d -print | while read dir; do
    count=$(ls -1 "$dir" 2>/dev/null | wc -l)
    if [ "$count" -gt 10000 ]; then
        echo "$count $dir"
    fi
done | sort -rn | head -10

Common sources of inode exhaustion: PHP session files, email spool directories, application cache files, npm node_modules.

Summary

Most disk space problems fall into three categories: log files that aren’t rotating, files that were deleted but not freed (open file descriptors), or accumulated cache/temporary files. Regular monitoring means you catch these before they cause outages.

A 15-minute audit of each new server — checking what’s installed, what’s logging where, and setting up disk monitoring — prevents most of the disk-related problems I’ve seen in production.

Scroll to Top