When a Linux disk is full, work in this order. Run df -h to see which filesystem is at 100%. Then run du -sh * | sort -h to walk down one directory at a time until you find the culprit, and use ncdu to browse it interactively. Finally, reclaim space with journalctl --vacuum-size and docker system prune.
df -h: which filesystem is full and whether inodes ran out
df -h prints size, used, available and use percentage for every mounted filesystem, in human-readable units (K, M, G). It comes first because it answers the question that matters before anything else: which partition is full? Cleaning /home is pointless if /var is the one at 100%.
df -h
df -h /var
df -iIf df -h shows free space but writes still fail with “No space left on device”, check df -i. You may have run out of inodes because of millions of tiny files: caches, sessions or mail queues. In that case size is irrelevant. File count is the problem, so look for the directory with the most entries, not the heaviest one.
du -sh * | sort -h: finding the directory that fills the disk
du -sh * | sort -h totals every entry in the current directory and sorts the results smallest to largest. The biggest offender lands on the last line, right above the prompt, which is all you need to read on a small screen.
cd /var
sudo du -sh * | sort -h
# from root, without crossing into other filesystems
sudo du -xh --max-depth=1 / 2>/dev/null | sort -h
# include hidden files and directories
du -sh .[!.]* * | sort -hKeep three details in mind. The * glob skips dotfiles, which is why the last line exists. -x stays on the starting filesystem and ignores /proc and network mounts. 2>/dev/null hides permission-denied noise. Repeat the command one level deeper each time until you reach the file. Every other flag is documented in the du manual page.
On large disks, du can run for minutes. Start it inside tmux: if the connection drops, the scan keeps going and the result is waiting when you reattach.
ncdu: browsing a full disk interactively
ncdu -x / scans the filesystem once and then shows a navigable tree sorted by size, so you no longer re-run du at every level. Install it with your distribution's package manager (apt install ncdu, dnf install ncdu).
sudo ncdu -x /
sudo ncdu -x /var/libInside ncdu, use these keys:
- the arrow keys, to move;
- Enter, to open a directory;
- the left arrow, to go back up;
d, to delete (it asks for confirmation);q, to quit.
On a phone, everything depends on having arrows and Esc within reach. termi1's own keyboard includes them, along with Ctrl, Tab and PgUp/PgDn for paging through long listings.
Deleted files still filling the disk: lsof +L1
If the du total is clearly below what df reports as used, some process is holding a deleted file open. The classic case is a log removed with rm while the service was still writing to it. The space is only released once that file descriptor closes.
sudo lsof +L1
# restart the service holding it, or empty the descriptor:
sudo truncate -s 0 /proc/PID/fd/NThe rule is simple: to empty a log that is in use, run truncate -s 0 file, not rm.
journalctl --vacuum: shrinking systemd logs that fill /var
journalctl --disk-usage reports how much space the systemd journal takes. The --vacuum-size and --vacuum-time options delete the oldest archived journal files until the limit you set is met.
journalctl --disk-usage
sudo journalctl --vacuum-size=500M
sudo journalctl --vacuum-time=2weeksA vacuum is a one-off. To keep the problem from coming back, set SystemMaxUse= in /etc/systemd/journald.conf and restart systemd-journald.
docker system prune: reclaiming the space Docker uses
docker system df breaks down the space used by images, containers, volumes and build cache. Run it before deleting anything so you know where the bulk actually is.
docker system df
docker system prune
docker system prune -a --volumesWith no flags, docker system prune removes stopped containers, unused networks, dangling images and build cache. -a also removes any image not used by a container. --volumes deletes unused volumes, and their data goes with them. On production hosts, read the output of docker system df -v before adding that flag.
df vs du vs ncdu for diagnosing a full disk
| Tool | What it measures | When to use it | Limitation |
|---|---|---|---|
df -h | Usage per mounted filesystem | First step: find which partition is full | Does not show which directory uses the space |
du -sh * | sort -h | Size of each entry in the current directory | Servers with no extra packages; easy-to-read output | Must be repeated per level; skips dotfiles |
ncdu -x / | Full tree sorted by size | Interactive browsing and confirmed deletion | Needs installing; needs arrow keys |
lsof +L1 | Deleted files still held open | When df and du disagree | Only finds them; does not free space |
Cleaning a full disk from your phone with termi1
Full-disk alerts tend to fire at bad hours, so it pays to fix them safely from a phone. Before truncating a log you might need later, download it over SFTP: termi1 has it built in, without leaving the session. Mosh keeps the connection alive when you switch from Wi-Fi to mobile data, and tmux keeps a long du running even if you close the app.
termi1's AI turns a sentence such as “which directories in /var use the most space” into the command and types it at the prompt without pressing Enter. On connections tagged as production, Production Guard holds back anything that deletes, such as docker system prune or journalctl --vacuum-size, before it reaches the prompt. The terminal is free on SSH terminal on Google Play. More guides are on the termi1 technical blog.
Frequently asked questions
Why do df and du report different sizes?
df and du disagree because df reads filesystem usage, while du adds up the files it can find. If a process keeps a deleted file open, df still counts it and du does not. Run sudo lsof +L1 to find it, then restart the service holding it.
Is docker system prune safe to run on a server?
docker system prune with no flags only removes stopped containers, unused networks, dangling images and build cache. The risk comes with -a, which deletes images without a container, and above all --volumes, which wipes the data in unused volumes. Check docker system df first.
How do I include hidden files with du -sh?
To make du -sh include hidden files, add the .[!.]* pattern to the glob: du -sh .[!.]* * | sort -h. The shell's asterisk does not expand names starting with a dot, so directories like .cache or .local can be missing from the totals and go unnoticed.
How do I stop journald from filling the disk again?
To cap journald permanently, set SystemMaxUse= in /etc/systemd/journald.conf to the maximum size you want, then restart systemd-journald. journalctl --vacuum-size only cleans once; the limit in the configuration file stops the journal from growing unchecked again.