Introduction
A classic Linux administration nightmare: df shows a filesystem at 100% but du adds up to far less than the total. This discrepancy happens when files are deleted but still held open by running processes, so the kernel cannot free the underlying blocks. The inode and data blocks remain allocated until every file descriptor referencing the file is closed.
Symptoms
df -hreports filesystem at 95-100% usagedu -sh /ordu -sh /varshows significantly lower usage thandf- Applications fail with
No space left on devicedespite apparent free space df -imay show normal inode usage (not an inode exhaustion issue)
Common Causes
- Log files rotated by
logrotatebut the writing process was not signaled to reopen - Large temporary files deleted while a process still writes to them
- Docker container layers referencing deleted base image files
- Database WAL or journal files unlinked but still in use
- Apache/Nginx access logs deleted without sending SIGHUP to the daemon
Step-by-Step Fix
- 1.Confirm the discrepancy between df and du:
- 2.```bash
- 3.df -h /var
- 4.sudo du -sh /var
- 5.# If df shows 45G used but du shows only 12G, deleted files are the culprit
- 6.
` - 7.Find deleted files still held open:
- 8.```bash
- 9.sudo lsof +L1 2>/dev/null | awk '$7 > 0 {print $0}' | sort -k7 -n -r | head -20
- 10.
` - 11.The
+L1flag shows files with link count less than 1 (deleted). The 7th column shows the file size. - 12.Identify the offending processes:
- 13.```bash
- 14.sudo lsof +L1 | grep -E "mysqld|nginx|java|docker"
- 15.
` - 16.Recover space by truncating the deleted file descriptors:
- 17.```bash
- 18.# Find the PID and file descriptor number from lsof output
- 19.# Truncate via /proc filesystem
- 20.PID=1234
- 21.FD=5
- 22.truncate -s 0 /proc/$PID/fd/$FD
- 23.
` - 24.Alternatively, restart the process holding the file:
- 25.```bash
- 26.sudo systemctl restart nginx
- 27.sudo systemctl restart mysql
- 28.
` - 29.Verify space is reclaimed:
- 30.```bash
- 31.df -h /var
- 32.
`
Prevention
- Configure
logrotatewithcopytruncatefor services that cannot be signaled, or usepostrotatescripts withkill -HUP - Monitor disk usage with alerts using
dfrather thandufor production monitoring - Use
lsof +L1as part of regular disk health checks - Implement filesystem quotas to prevent any single process from consuming all space