How to Safely Find and Reclaim Disk Space on Linux

A full disk rarely arrives at a convenient time. A web application may stop writing logs, SSH sessions may fail to start, databases may become read-only, or a routine update may abort halfway through. The tempting response is to delete a large directory immediately, but that can remove application data or break a running service.

This guide presents a safer workflow: measure first, identify the filesystem and largest consumers, clean low-risk data, then verify both free space and application health. The commands work across Ubuntu and Debian, RHEL and Fedora, and AlmaLinux, with package-manager differences called out clearly.

TL;DR

  • Run df -hT to find which filesystem is full and df -ih to check inode exhaustion.
  • Use du to inspect directories on the affected filesystem, starting at the root rather than guessing.
  • Clean package caches and old systemd journal entries with the distro-appropriate commands.
  • Before deleting anything manually, confirm its path, owner, purpose, and whether a process still has it open.
  • Run df -hT again, then verify the affected service and review logs.

Why disk-space management matters

Linux separates storage into filesystems such as /, /var, /home, and sometimes a dedicated boot partition. A message saying the server is out of space does not necessarily mean every filesystem is full. A 100% full /boot requires a different remedy from a 100% full /var.

There are also two different limits. Blocks hold file data, while inodes track individual files and directories. A system can have gigabytes free but still fail to create a file when it has exhausted its inodes, often because an application generated millions of tiny temporary or cache files.

Careful cleanup is therefore more than deleting large files. It is a repeatable diagnostic process that protects data, keeps package management healthy, and gives you evidence for preventing the next incident. For a broader maintenance routine, see the AdminHint guide to Linux server maintenance.

Prerequisites and safety rules

  • A shell account with sudo access. Become root only when a command genuinely requires it.
  • Enough time to inspect output rather than pasting a destructive command blindly.
  • A current backup or snapshot for important production systems.
  • Knowledge of the application or service using the affected machine.
Warning: Never run rm -rf against a path you have not inspected and confirmed. A missing slash, wildcard, or variable can turn a targeted cleanup into catastrophic deletion. Do not delete database files, package database files, files under /etc, or active application data merely because they are large.

1. Diagnose the full filesystem before changing anything

Start with filesystem-level measurements:

df -hT
 df -ih

The -h flag presents human-readable sizes, -T displays the filesystem type, and -i reports inode usage. A typical result might look like this:

Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/vda2      ext4   40G   38G  1.1G  98% /
/dev/vda1      ext4  976M  210M  700M  24% /boot

eFilesystem     Inodes IUsed IFree IUse% Mounted on
/dev/vda2        2.6M  1.9M  700K   74% /
/dev/vda1        64K    310   63K    1% /boot

The first report shows block consumption. The second shows inode consumption. Ignore harmless pseudo-filesystems such as tmpfs unless a specific application is using them. Record the mount point with the highest usage. In this example, the investigation should focus on /, not /boot.

To see mounted filesystems in a readable hierarchy, use:

findmnt -D

This helps explain whether a directory such as /var is its own mount. If it is separate, space used there will appear under its own row in df and should be investigated independently.

2. Find the largest directories without crossing mounts

For a full root filesystem, inspect the first directory level:

sudo du -xhd1 / 2>/dev/null | sort -h

Here du estimates directory usage, -x stays on the current filesystem, -h uses readable units, and -d1 limits the report to one level. The error redirect hides permission warnings so the size report is easier to read. A plausible output is:

120M    /boot
2.4G    /home
8.7G    /usr
25G     /var
39G     /

Continue into the largest directory. If /var is the problem, run:

sudo du -xhd1 /var 2>/dev/null | sort -h

Then inspect the likely child, such as /var/log, /var/cache, or /var/lib:

sudo du -xhd1 /var/log 2>/dev/null | sort -h
sudo du -xhd1 /var/cache 2>/dev/null | sort -h

For a more interactive view, install ncdu if your change policy permits it. On Ubuntu and Debian:

sudo apt update
sudo apt install ncdu
sudo ncdu -x /

On Fedora, RHEL, and AlmaLinux:

sudo dnf install ncdu
sudo ncdu -x /

The -x option prevents the scan from wandering into other mounted filesystems. In ncdu, use the arrow keys to inspect directories and press q to quit. Treat its delete option as an advanced feature; manual deletion should not be your first response.

3. Check for deleted files still held open

Sometimes du cannot find the data responsible for the full disk. A process may have deleted a log file but kept the file descriptor open. The blocks remain allocated until the process closes the file or restarts.

sudo lsof +L1

A result may resemble:

COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NLINK NODE NAME
java     1842 app    12w   REG  252,2  524288000     0 8123 /var/log/app.log (deleted)

+L1 asks lsof to show open files with fewer than one link, which normally means deleted files. Note the process and service rather than deleting anything else. Restart the owning service during an approved maintenance window:

sudo systemctl restart app.service
sudo systemctl status app.service --no-pager

If a restart is not safe, coordinate with the application owner. Killing a process can cause data loss or interrupt requests. After a controlled restart, run df -hT again.

4. Reclaim package-manager cache safely

Package caches are usually low-risk cleanup targets because they contain downloaded installation packages, not the installed program itself. Keep in mind that a cache can be useful when reinstalling without network access, so follow your organization’s retention policy.

Ubuntu and Debian

sudo apt clean
sudo apt autoclean
sudo apt autoremove

apt clean removes all cached package archives. apt autoclean removes only archives that can no longer be downloaded. apt autoremove proposes removal of automatically installed packages no longer needed. Review the proposed package list carefully and answer y only when it is appropriate. You can preview the cleanup without applying it:

sudo apt autoremove --dry-run

Do not manually remove files from /var/lib/dpkg or /var/lib/apt/lists while package operations are running. Those directories support package-management state.

Fedora, RHEL, and AlmaLinux

sudo dnf clean packages
sudo dnf autoremove

dnf clean packages removes downloaded RPM packages. dnf autoremove proposes dependencies that are no longer required. Review the transaction summary before confirming. On older RHEL or CentOS-compatible installations that still use YUM, use:

sudo yum clean packages

Do not delete RPM database files under /var/lib/rpm. If the package database is damaged, use the distribution’s documented recovery procedure rather than improvised removal.

5. Reduce systemd journal growth

Systemd journal files commonly occupy /var/log/journal. First measure their current size:

sudo journalctl --disk-usage

Example output:

Archived and active journals take up 3.2G in the file system.

A time-based cleanup is easy to explain and audit:

sudo journalctl --vacuum-time=14d

This removes archived entries older than 14 days. A size-based cleanup is useful during an emergency:

sudo journalctl --vacuum-size=500M

The command affects archived journal files; the currently active file may remain until rotation. Confirm the result:

sudo journalctl --disk-usage
Warning: Do not erase all logs just to make a percentage drop. Logs may be required for security investigations, incident response, compliance, or diagnosing the original failure. Preserve or forward important logs before reducing retention.

To prevent recurrence, inspect the journal configuration:

sudo grep -R 'SystemMaxUse\|SystemKeepFree\|MaxRetentionSec' /etc/systemd/journald.conf /etc/systemd/journald.conf.d 2>/dev/null

If your policy allows a persistent limit, create a drop-in rather than editing a vendor file. For example:

sudo install -d -m 0755 /etc/systemd/journald.conf.d
sudo sh -c 'printf "[Journal]\nSystemMaxUse=1G\nSystemKeepFree=2G\n" > /etc/systemd/journald.conf.d/size.conf'
sudo systemctl restart systemd-journald

SystemMaxUse caps journal usage, while SystemKeepFree tells journald to leave space available. Select values appropriate for the disk and retention requirements; do not copy them blindly onto a tiny system.

6. Investigate logs and application data carefully

If logs are the largest consumer, identify the responsible service and its rotation policy:

sudo ls -lhS /var/log | head -20
sudo systemctl list-timers --all | grep -E 'logrotate|journal'

Logrotate configuration commonly lives in /etc/logrotate.conf and /etc/logrotate.d. Test the configuration without changing files:

sudo logrotate -d /etc/logrotate.conf

The -d flag enables debug mode. It reports what logrotate would do but does not perform rotation. Avoid truncating a live log with shell redirection unless the application owner has approved it. Some programs keep an open file descriptor and will continue writing to the same inode even after a confusing manual change.

Directories such as /var/lib/postgresql, /var/lib/mysql, container storage, and virtual-machine images contain application data. Their size may be expected. Use the application’s own retention, backup, and prune commands; never remove individual data files because they look old. See the related AdminHint article on troubleshooting systemd services when cleanup exposes a failed daemon.

7. Check temporary files and inode exhaustion

Inspect temporary directories without deleting their contents blindly:

sudo du -xhd1 /tmp /var/tmp 2>/dev/null | sort -h
sudo find /tmp -xdev -type f -printf '%s %p\n' 2>/dev/null | sort -n | tail -20

Temporary-file cleanup is normally managed by systemd-tmpfiles. Review its configuration and run a cleanup according to the system’s rules:

sudo systemd-tmpfiles --clean

For inode pressure, locate directories containing many entries:

sudo find /var -xdev -type f 2>/dev/null | cut -d/ -f1-4 | sort | uniq -c | sort -n | tail -20

This is an approximate count grouped by the first four path components. If the system is critically full, save output to another filesystem because writing diagnostic files on the affected filesystem may fail.

8. Verify the cleanup and the service

Verification should cover more than a lower percentage in df:

df -hT
df -ih
sudo journalctl --since '-15 minutes' -p warning --no-pager
sudo systemctl --failed

The first two commands confirm block and inode availability. The journal query displays warning-and-higher messages from the last 15 minutes. systemctl --failed lists failed units; no output usually means none are currently failed.

Then test the workload: request the web endpoint, connect to the database, run the scheduled job, or perform the normal health check. A successful cleanup that leaves the application broken is not a successful incident resolution.

Common mistakes

  • Using du / without -x: mounted filesystems can make the totals misleading and cause long scans.
  • Confusing deleted-open files with visible files: use lsof +L1 when df is much larger than du.
  • Deleting all of /var/log: this removes evidence and can confuse services that expect a log path.
  • Running autoremove without reviewing it: a dependency that looks unused may support a manually installed workload.
  • Ignoring inodes: check df -ih when free gigabytes do not resolve file-creation errors.
  • Cleaning a database directory manually: use database-native retention and backup procedures.

Best-practice checklist

Stage Action Evidence to retain
Measure Run df -hT and df -ih Affected mount and usage percentages
Locate Use du -xhd1 and descend gradually Largest directories and files
Explain Check package caches, journals, logs, open deleted files, and application data Cause of growth
Change Use package-manager and journald cleanup tools Commands and approvals
Verify Repeat disk checks and test services Before-and-after values and health results
Prevent Set retention, rotation, monitoring, and alert thresholds Configuration and owner

Fallback troubleshooting

If cleanup appears successful but df does not change, run sudo lsof +L1 and look for deleted-open files. If du cannot read a directory, do not assume it is empty; use sudo and inspect permissions. If apt or dnf refuses to run because another package transaction is active, wait for the existing transaction or investigate its process rather than deleting lock files.

If the root filesystem reaches 100% and commands fail, remove only a small, known-safe amount first, such as an old package archive or an approved journal archive. Redirect command output to a mounted disk with available space. If the machine cannot boot because /boot is full, use the distribution’s package tools to remove obsolete kernels while retaining the running kernel and at least one known-good fallback.

Conclusion

Disk cleanup is safest when treated as diagnosis followed by controlled maintenance. Identify the full filesystem, distinguish blocks from inodes, locate the real consumer, and prefer supported tools such as apt, dnf, journalctl, logrotate, and systemd-tmpfiles. Finish by verifying the filesystem, logs, and application—not just the free-space number. With monitoring and sensible retention policies, the next full-disk alert becomes a routine task instead of an emergency.

FAQ

Is it safe to delete everything in /tmp?

No. Active programs may use temporary files. Prefer systemd-tmpfiles --clean and inspect unusual files before manual removal.

How much free space should a Linux server keep?

There is no universal number. Keep enough for package updates, logs, temporary files, and application bursts. Alert before 80–85% and define a stricter threshold for critical filesystems such as /boot.

Why does du show less space than df?

Common causes are deleted files still held open, files hidden beneath a mount point, reserved filesystem blocks, or different filesystem scopes. Start with lsof +L1 and findmnt.

Can I remove old kernels?

Yes, but use the distribution’s package manager and keep the running kernel plus a known-good fallback. Never delete kernel files manually from /boot.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *