Why rm Doesn't Free Disk Space in Linux (and How to Fix)

작성자

카테고리:

← 피드로
DEV Community · Doogal Simpson · 2026-09-29 개발(SW)
Cover image for Why rm Doesn't Free Disk Space in Linux (and How to Fix)

Doogal Simpson

When you run rm on a file in Linux, the OS only removes the directory entry (the pointer). If a running process still has an open file descriptor to that file, the disk space is not reclaimed until the process is restarted or the file descriptor is closed.

Picture this: It is 2:00 AM. A critical production alert wakes you up because a bare-metal server has run out of disk space. You SSH in, run df -h, and confirm the disk is at 100% capacity. After digging around, you find a massive 50GB debug log file. Relieved, you run rm debug.log, verify with ls that it is gone, and run df -h again—only to find the disk is still at 100% capacity.

Back in the days before Kubernetes, Docker, and automatic container rescheduling, I had to manage physical servers manually. I spent my time SSHing directly into physical boxes, copying files over, and running them right on the web server. When disk space issues hit, I was the one who had to dig through the filesystem to find what was eating up the storage. This specific disk space trap was a classic Unix rite of passage for me, and it reveals a fundamental aspect of how Linux manages filesystems, inodes, and file descriptors.

Why does Linux say a deleted file is still using disk space?

Linux separates a file’s name from its actual data on the disk. When you run rm, you are only removing the directory link (the pointer), not the underlying data blocks. The operating system will only reclaim that disk space when both the link count and the process reference count for that file reach zero.

Under the hood, Linux uses inodes to represent filesystem objects. A file name in a directory is just a hard link pointing to an inode. When you execute rm, you are calling the unlink system call. This decrements the link count of the inode.

However, the filesystem also tracks how many running processes have an active file descriptor pointing to that inode. If a service (like an active web server or database) is still writing to or reading from that file, the process reference count remains above zero. Think of it like a library book: rm removes the card from the catalog, but if a reader still has the book open on their desk, the book hasn’t actually left the building. The OS keeps the data blocks intact to prevent the running application from crashing.

How do you find which process is holding a deleted file open?

To find which process is keeping a deleted file alive, use the lsof (list open files) utility. By filtering the output for files marked as “deleted”, you can pinpoint the exact Process ID (PID) and file descriptor (FD) holding the space hostage.

Here is the command to run when you find yourself in this situation:

lsof +L1
# Or alternatively:
lsof | grep deleted

Enter fullscreen mode Exit fullscreen mode

The output will show you exactly which process is keeping the file alive on disk:

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME node 1234 web 4w REG 8,1 53687091200 987654 /var/log/debug.log (deleted)

This output tells you that the process running under PID 1234 still has file descriptor 4 open for writing (w) to the deleted file.

How do you free up disk space without restarting the service?

The cleanest way to free up space without restarting a process is to truncate the file descriptor to zero bytes via the /proc directory. Alternatively, you can gracefully reload or restart the target service to force it to release the file handle.

If restarting the service is not an option—perhaps because it is a critical production database with high uptime requirements—you can bypass rm entirely. Here is how to handle this scenario:

  • The Truncation Trick (Preventative): Instead of running rm, truncate the file. Running > debug.log empties the file in place. The process keeps its file descriptor, but the disk space is instantly reclaimed.
  • The /proc Writeback (Post-deletion): If you already deleted the file, find the PID and FD using lsof. You can force-truncate the file by redirecting an empty string directly to its file descriptor entry inside the /proc filesystem:
  true > /proc/1234/fd/4

Enter fullscreen mode Exit fullscreen mode

  • Graceful Service Reload: Signal the application to close and reopen its log files (often done via SIGHUP if the application supports it), which forces the process to release the dead file descriptor and create a new one.

Frequently Asked Questions

Why does df show 100% disk usage but du shows much less?

The du (disk usage) command estimates space by traversing the directory tree, meaning it cannot see deleted files because their directory pointers are gone. Conversely, df (disk free) queries the filesystem superblock directly, which accurately reflects that the storage blocks are still reserved by open file descriptors.

Can a reboot solve the “deleted file still using space” issue?

Yes, restarting the system or the specific container will terminate all running processes, forcing them to close their open file descriptors. Once the process reference count drops to zero, the operating system immediately reclaims the deleted file’s disk space.

Is there a way to force Linux to delete a file even if it is open?

No, you cannot force the filesystem to free the blocks while a process holds an active file descriptor. This safety mechanism prevents kernel panics and application crashes that would occur if a process attempted to read or write to non-existent disk blocks.

원문에서 계속 ↗