Tutorials

Full Server Disk: Find the Culprit and Free Up Space

Server disk full and site down? With du, ncdu, lsof, and df inode, find the culprit in minutes and free up space without deleting the wrong thing.

Tutorials

The site won't come up, MySQL throws a Disk full error, or SSH refuses to let you in because it can't write the session file. First of all, accept this: until you know which path has eaten the space, any deletion is a gamble. A wrong rm -rf in the wrong path will take down both the site and the backup. So the order of operations matters.

First df, then du; not the other way around

Start with df -h to see which mount is full. If the / partition is full but /home is healthy, limit your search to that same tree. One point many people miss: also run df -i. It's possible that disk space is free but inodes are exhausted.

df -h
df -i
du -xhd1 / 2>/dev/null | sort -h

The -x flag in du keeps it from crossing filesystem boundaries; without it, if there's an NFS or bind mount inside the path, the numbers become meaningless. -d1 gives one level of depth, and sort -h puts the largest at the end of the list. After finding the suspicious folder, repeat the same command on it until you reach the file.

ncdu answers faster than du

On high-traffic servers, du over millions of files takes several minutes and eats disk I/O. ncdu indexes the tree once and then you navigate with the arrow keys. If it's not installed, install it from your distribution's repository:

ncdu -x /var

In the output, you delete files with d and toggle between percentage and raw size with g. One practical warning: ncdu only sees what's visible in the filesystem. Open deleted files and hidden files deep inside paths must be hunted separately.

A deleted file that's still taking up space

This is the most classic trap. You clear the log with rm, df is still full, and no file shows up in du. The reason is simple: a process like nginx or PHP-FPM is still holding that file's file descriptor open, and the kernel won't free the blocks until it's closed. Find it with lsof:

lsof +L1
lsof -nP | grep deleted

The output of lsof +L1 shows files whose link count has dropped to zero. The last column gives the size that would be freed. The solution isn't to delete the file; it's to restart that service. If it's nginx, systemctl reload nginx isn't enough because the master process has the file open; systemctl restart nginx is required. Before restarting, make sure the config is valid, otherwise the service won't come up and now you have two problems.

This is where people go wrong

The most common mistake I see in tickets is this: someone clears access.log with rm, df doesn't change, and they conclude "the disk is broken." In reality, the web server process has the file open. The sign is exactly this: du on the log folder shows a small number but df gives the same previous percentage. The right way is to truncate, not delete:

truncate -s 0 /var/log/nginx/access.log

This command keeps the file in place, preserves the inode, and the process continues writing without a restart. For rotating logs, configure logrotate with copytruncate so this problem doesn't recur.

When inodes run out, not space

If df -h says 40% free but df -i is at 100%, the problem is elsewhere. This happens when you have millions of small files: PHP sessions, cache files, mail queues, or spam piled up in /var/spool. Disk space is useless because inodes are exhausted. Find the culprit with this command:

for d in /var/* /home/*; do echo "$(find $d -xdev 2>/dev/null | wc -l) $d"; done | sort -n

Clearing expired sessions usually frees up several million inodes. If the number of small files is structurally high, the temporary fix is periodic cleanup, and the real fix is moving that data to a filesystem with more inodes or using Redis for sessions.

Comparing the tools; which one to run when

ToolWhat it's forLimitation
df -hSeeing free space per mountDoesn't see open deleted files
df -iDetecting inode exhaustionOnly count, not size
du -xhd1Finding the large folderSlow over millions of files
ncduInteractive exploration and quick deletionRequires installation and initial indexing
lsof +L1Open deleted filesRequires root

The logical order is: df -h and df -i for high-level diagnosis, then ncdu to find the path, and lsof +L1 when the numbers don't add up. If after these three steps you still can't find the space, the problem is probably at another layer and you need to look into services that are actively writing.

Preventing recurrence; not just freeing up

Freeing up space is half the job. If you don't close the root cause, you'll file the same ticket two weeks later. Three practical steps:

  • For logs, configure logrotate with a specific maxsize and rotate, not just daily rotation.
  • Set up a df alert on the WordPress uploads folder and the backup folder; for example, a cron that emails you when it goes above 85%.
  • Don't keep old backups on the same server. A backup on the same disk that's filling up isn't a backup.

If you have a WordPress site, a large portion of these small files come from plugins and cache. A WordPress plugin audit often removes several gigabytes and hundreds of thousands of extra files, without losing anything. For high-traffic sites, separating logs and sessions onto an independent partition prevents the whole server from going down. If you're still working on a shared server with a single partition, Linux hosting with separate partitioning reduces this risk.

For more commands and service configurations, ServerNet's documentation and knowledge base is a good reference. And if you want to run this same check on your own site, the free tools are a quick starting point.

Frequently asked questions

Why does df still not show free space after deleting a file?

Because a process has that file open and the kernel won't free the blocks until the file descriptor is closed. Find the process with lsof +L1 and restart that service. If you want to empty a log file, use truncate -s 0 instead of rm.

What's the difference between df -h and df -i, and which is more important?

df -h shows the amount of space used and df -i shows the number of inodes used. Both matter. If space is free but inodes are at 100%, you can't create new files and you'll get errors like No space left on device, just as if the disk were actually full.

How do I figure out which folder has filled the disk?

Start from the root with du -xhd1 / and pick the largest folder, then repeat the same command inside it until you reach the file. If there are many files, ncdu -x /var is faster and easier because it indexes once.

Is it safe to delete logs with rm?

No, if a service is writing to that file. Deleting makes the file disappear from du's view but doesn't free the space, and the service keeps writing to the unnamed file. The right way is to truncate the file or use logrotate with the copytruncate option.

ServerNet Support

ServerNet engineering & editorial team — specialists in infrastructure, networking and web hosting.

WordPress Hosting
Share:

Comments 0

No comments yet — be the first!

Leave a comment

Related service

WordPress Hosting

A purpose-built WordPress stack on LiteSpeed Enterprise and NVMe — auto-install, secure updates, staging and caching that keeps you on top of Google.