A full Linux disk rarely announces itself politely. A web application may stop accepting uploads, SSH logins may become unreliable, package updates can fail, and a database may suddenly report that it cannot write temporary files. The confusing part is that deleting one large-looking file does not always solve the problem: the filesystem might be full of inodes, a deleted file may still be held open by a running process, or a mount point may be hiding files beneath it.
This guide presents a careful, beginner-friendly method for finding and fixing disk-space problems on Ubuntu, Debian, RHEL, Fedora, and AlmaLinux. The goal is not merely to delete data. It is to diagnose first, reclaim only space you understand, verify the result, and add safeguards so the incident is less likely to return.
TL;DR
- Run
df -hTto identify the full filesystem anddf -ihto check inode exhaustion. - Use
duon the affected filesystem to locate large directories, while excluding other mounted filesystems. - Inspect logs, package caches, temporary files, old kernels, container images, and deleted-but-open files before removing anything.
- Use the distro package manager for cache cleanup. Do not blindly delete files from
/var/libor database directories. - Run
df -hTagain, verify the service, and establish log rotation, retention, and monitoring.
Why this matters
Linux services need free storage for logs, sockets, temporary files, package transactions, database journals, and memory-backed operations. A filesystem at 100 percent capacity can prevent an otherwise healthy service from starting. Root filesystems deserve particular attention because a full / can affect almost every system component.
There are two related limits. Data blocks store file contents, while inodes track files and directories. Millions of tiny files can consume all inodes even when gigabytes remain free. Conversely, a few large backups can consume all data blocks while inode usage remains low. The first diagnostic step must distinguish these conditions.
Prerequisites and safety rules
- Have a shell session with
sudoaccess. If you are working remotely, keep a second session open before changing services or logs. - Know whether the host runs important databases, containers, mail services, or application workloads. Their data directories require application-aware cleanup.
- Record the current state before changes. A short command transcript can make recovery and incident reporting much easier.
- Never remove an unfamiliar file merely because it is large. Confirm its owner, path, age, and purpose first.
rm -rf, truncating active logs, deleting package metadata, and pruning container images can cause data loss or service disruption. Start with read-only commands, make a backup when appropriate, and delete only a path you have positively identified.1. Diagnose the filesystem before fixing it
Start with filesystem-level information:
df -hT
df -ih
The df command reports free space for mounted filesystems. The -h flag makes sizes human-readable, -T shows the filesystem type, and -i reports inode usage instead of data blocks. A typical result might look like:
Filesystem Type Size Used Avail Use% Mounted on
/dev/vda2 ext4 40G 39G 420M 99% /
/dev/vda1 ext4 512M 86M 392M 18% /boot
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/vda2 2.6M 1.1M 1.5M 43% /
/dev/vda1 32K 312 32K 1% /boot
Here, the root filesystem is nearly full, but inodes are healthy. If IUse% is close to 100 percent, search for directories containing huge numbers of small files, such as mail queues, cache trees, session files, or application-generated temporary files.
Check mounts and recent kernel messages when the output seems surprising:
findmnt -D
mount | column -t
sudo dmesg --level=err,warn | tail -n 30
findmnt -D displays mounted filesystems and usage; column -t makes mount output easier to read. The dmesg command may reveal I/O errors or a read-only remount. If you see filesystem errors, do not treat the issue as ordinary cleanup: plan a maintenance window and investigate storage health.
2. Locate the space consumer without crossing mount points
Once you know the affected mount, summarize its top-level directories. Run this from the filesystem root:
sudo du -xhd1 / 2>/dev/null | sort -h
The du command estimates directory usage. -x stays on one filesystem, preventing a mounted data disk from distorting the result; -h makes sizes readable; and -d1 limits the summary to one directory level. The redirection hides permission warnings, while sort -h orders values naturally from small to large.
Typical output might end with:
1.2G /opt
3.8G /home
11G /var
17G /
Continue into the largest directory. For example:
sudo du -xhd1 /var 2>/dev/null | sort -h
sudo du -xhd1 /var/log 2>/dev/null | sort -h
sudo du -xhd1 /var/lib 2>/dev/null | sort -h
Do not assume /var/log is the culprit. Package caches, container storage, databases, virtual machine images, and application uploads often live under /var. If du totals are much smaller than df reports, investigate deleted files still held open by processes.
3. Check deleted files that still consume space
When a process has a file open, deleting its directory entry does not release the blocks until the process closes the file. This commonly happens after manually removing a log while its service continues writing to the old file.
sudo lsof +L1
lsof lists open files, and +L1 selects files with fewer than one directory link, which normally means deleted files. Look for a large value in the SIZE/OFF column and note the process ID and service name.
The safest remedy is to restart the owning service during an approved window:
sudo systemctl restart service-name
sudo lsof +L1
Replace service-name with the actual unit, such as nginx or httpd. Verify the service afterward with systemctl status service-name --no-pager. If restarting is not acceptable, consult the service documentation for a reload or log-reopen signal. Avoid writing to an open file descriptor manually unless you understand the application and have a recovery plan.
4. Reclaim package-manager cache safely
Package caches are usually safe candidates because packages can be downloaded again. Use the package manager that matches the operating system.
Ubuntu and Debian
sudo apt-get clean
sudo apt-get autoremove
apt-get clean removes downloaded package archives from the local cache. autoremove proposes packages that were installed as dependencies but are no longer required. Review its transaction list before confirming. A less aggressive option is:
sudo apt-get autoclean
autoclean removes only obsolete archive files. On a production server, inspect the proposed removal first with sudo apt-get -s autoremove; -s simulates the operation without changing the system.
RHEL, Fedora, and AlmaLinux
sudo dnf clean packages
sudo dnf autoremove
dnf clean packages removes cached package payloads. autoremove identifies no-longer-needed dependencies. Preview the cleanup where supported with:
sudo dnf autoremove --assumeno
The --assumeno option answers no to prompts so you can inspect the transaction. Older RHEL or AlmaLinux installations may use yum; the equivalent commands are sudo yum clean packages and sudo yum autoremove. Do not delete /var/lib/dnf, /var/lib/yum, or repository metadata by hand.
5. Inspect logs and journal retention
Systemd journals can grow substantially if persistent retention is not configured. Measure journal usage first:
sudo journalctl --disk-usage
Example output:
Archived and active journals take up 2.4G in the file system.
To remove archived entries older than 14 days:
sudo journalctl --vacuum-time=14d
Alternatively, keep the journal below a size limit:
sudo journalctl --vacuum-size=500M
--vacuum-time removes archived files older than the specified age; --vacuum-size removes the oldest archived files until the total is below the target. Vacuuming does not erase currently active journal files, and it does not replace application log rotation.
For persistent prevention, create a drop-in configuration:
sudo install -d -m 0755 /etc/systemd/journald.conf.d
sudo sh -c 'printf "[Journal]\nSystemMaxUse=500M\nMaxRetentionSec=14day\n" > /etc/systemd/journald.conf.d/size-limit.conf'
sudo systemctl restart systemd-journald
The install -d command creates the directory with controlled permissions. The configuration limits journal storage and retention. Choose values appropriate for your audit and compliance requirements; do not shorten retention blindly on systems that require historical logs.
6. Clean temporary files and old packages carefully
Systemd-tmpfiles can remove temporary data according to distribution policy:
sudo systemd-tmpfiles --clean
This is preferable to manually deleting everything under /tmp or /var/tmp. Temporary files may belong to active jobs, so inspect unusual contents before using broad deletion commands.
On Ubuntu and Debian, old kernels are normally handled by package management. First inspect installed kernels:
dpkg -l 'linux-image*' | grep '^ii'
On RHEL, Fedora, and AlmaLinux, list installed kernel packages with:
rpm -q kernel
Keep the running kernel and at least one known-good fallback. Removing the currently running kernel or all fallback kernels can leave a machine unbootable after the next restart. Use the distro’s normal package cleanup tools, and reboot only after confirming a tested kernel remains.
7. Special cases: containers, databases, and hidden files
Container storage can consume the majority of /var. For Docker, inspect before pruning:
sudo docker system df
sudo docker image ls
sudo docker container ls -a
Only after confirming unused objects can be removed should you consider sudo docker system prune. The command can remove stopped containers, unused networks, dangling images, and build cache. Adding -a removes all images not used by a running container and is substantially more destructive. For Podman, use sudo podman system df and review sudo podman system prune.
Never delete database files, WAL logs, binary logs, or queue directories with rm. Use the database’s retention and checkpoint procedures. A database may also reserve space that du reports differently from the logical data you expect.
Another overlooked case is a file hidden beneath a mount point. If a directory contained large files before a disk was mounted there, those files remain on the underlying filesystem but are invisible while mounted. Booting into rescue mode or temporarily unmounting the filesystem may be required. Do this only with a maintenance plan; unmounting an active filesystem can interrupt services.
Verification after cleanup
Always prove that the change worked:
df -hT
df -ih
sudo du -xhd1 /var 2>/dev/null | sort -h
sudo systemctl --failed
Free space should increase on the affected mount, and inode usage should fall if that was the problem. systemctl --failed lists failed units; an empty result is normal. Check the affected application directly, inspect recent errors, and confirm that new logs can be written:
sudo journalctl -p err -b --no-pager | tail -n 30
sudo systemctl status your-service --no-pager
The -p err filter selects error priority, -b limits results to the current boot, and --no-pager keeps output suitable for scripts and tickets.
Fallback troubleshooting
- Space does not return after deleting a file: run
sudo lsof +L1and restart or reload the owning process safely. dfis high butduis low: check deleted-open files, hidden files beneath mounts, snapshots, and storage-layer reservations.- Inodes are exhausted: use
sudo find /var -xdev -type f | cut -d/ -f1-4 | sort | uniq -c | sort -nto locate file-heavy areas, then address the application creating them. Test this command on a large tree because it can be slow. - Cleanup fails with read-only errors: inspect
dmesgfor I/O or filesystem errors and schedule filesystem checks from rescue mode rather than forcing writes. - The disk fills again quickly: identify the writer with
sudo iotop -oif installed, inspect service logs, and check for a runaway debug setting or failed log rotation.
Common mistakes and best practices
- Do not run
rm -rf /var/log/*. It destroys useful evidence and may remove special files or application-managed directories. - Do not use
du /without-xwhen investigating one mount; other disks can make the result misleading. - Do not confuse a full filesystem with a full disk device. Expanding a partition or logical volume requires backups, a change plan, and separate verification.
- Keep application logs under rotation, compress older logs, and set retention according to operational and legal requirements.
- Monitor filesystem and inode percentages, especially
/,/var,/home, and database mounts. Alert before 100 percent; 80 to 90 percent is a useful starting threshold. - Document which cleanup commands are approved for each server role. A web server, database server, and container host should not share an unreviewed cleanup script.
Practical checklist
| Stage | Command or action | Success signal |
|---|---|---|
| Measure | df -hT and df -ih |
Affected mount and limit are known |
| Locate | sudo du -xhd1 /mount |
Largest directory is identified |
| Inspect | Logs, caches, containers, deleted-open files | Cause is understood before deletion |
| Clean | Distro-specific package and journal commands | Only approved, recoverable data is removed |
| Verify | Repeat df, check services and errors |
Space is available and workloads are healthy |
| Prevent | Rotation, retention, alerts, and documented ownership | The condition is detected earlier next time |
Conclusion
Recovering Linux disk space is safest when treated as a diagnosis problem, not a deletion contest. Begin with df, separate block exhaustion from inode exhaustion, narrow the search with mount-aware du, and account for open deleted files. Then use Ubuntu/Debian or RHEL-family package tools, journal retention, and application-specific cleanup rather than indiscriminate removal. Afterward, verify both storage and service health, and add monitoring so a full disk becomes an early warning instead of an outage.
FAQ
Is it safe to delete everything in /tmp?
Not blindly. Active programs may use temporary files. Prefer systemd-tmpfiles --clean and follow the distribution’s policy.
Why does df show more usage than du?
Deleted files still held open, files hidden below mount points, snapshots, and filesystem reservations can explain the difference. Start with lsof +L1.
Can I delete old journal files manually?
Use journalctl --vacuum-time or --vacuum-size instead. These options understand journal files and avoid unnecessary corruption risks.
How often should I check disk usage?
Use continuous monitoring for production systems. For small servers, schedule a daily check and alert well before the filesystem reaches capacity.
For related operational guidance, see our Linux log rotation guide, systemd service troubleshooting tutorial, and Linux disk monitoring checklist.