- Load average is not a percentage. Compare it against your core count: load 4 on 4 cores is fully busy, load 4 on 16 cores is quiet.
- Read the
availablecolumn infree -h, notfree. Linux uses spare RAM for cache and hands it back on demand. - High
wain top means processes are waiting on disk, and adding CPU will not help. dfreports free space;dureports what is using it. Check inodes too: a disk can be full with space remaining.- A single reading tells you very little. Take three, a few minutes apart, before you conclude anything.
How do I check CPU usage on a Linux server?
Start with uptime for the three load averages, then top for the breakdown by process. Load average counts processes running or waiting to run, so it must be read against the number of cores you have. It is not a percentage and never was.
$ uptime
10:24:31 up 47 days, 3:12, 2 users, load average: 2.31, 1.87, 1.42
# 1min 5min 15min
# How many cores do you have?
nproc
# Load per core: the number that actually means something
echo "$(cut -d' ' -f1 /proc/loadavg) / $(nproc) cores"| Load on a 4-core server | Means |
|---|---|
| Under 4.0 | Nothing is waiting. Healthy |
| Around 4.0 | Fully used with no spare capacity |
| 8.0 | Twice the work the machine can do. Requests are queueing |
| 1min far above 15min | A spike happening right now |
| 15min far above 1min | It has already passed. Look at the logs, not at top |
The last two rows are why you read all three figures rather than just the first.
top
# %Cpu(s): 12.5 us, 3.1 sy, 0.0 ni, 82.2 id, 2.1 wa, 0.0 hi, 0.1 si
# ^^^^ user ^^^ system ^^^^ idle ^^^ I/O WAIT
# Useful keys inside top:
# P sort by CPU
# M sort by memory
# 1 show every core separately
# c show the full command line
# k kill a process
# q quit
# htop is far easier to read if you can install it
sudo apt install -y htop && htopwa is the number people skip. It is the percentage of time the CPU spent idle waiting for disk.High wa is a disk problem, not a CPU problem
If wa is consistently above 10 percent, your processes are blocked waiting for storage. A faster or larger CPU changes nothing. The fix is faster disks, less I/O, or more RAM so the filesystem cache absorbs the reads.
How do I check memory usage correctly?
free -h is the command, and available is the column. Linux deliberately fills unused RAM with filesystem cache, so the free column is almost always small and almost always irrelevant. Cache is handed back to any process that needs it.
$ free -h
total used free shared buff/cache available
Mem: 7.8Gi 3.1Gi 262Mi 145Mi 4.4Gi 4.2Gi
Swap: 2.0Gi 128Mi 1.9Gi
# ^^^^^^ ^^^^^^
# looks alarming the truth: 4.2Gi spare
# What is using it, biggest first
ps -eo pid,ppid,rss,comm --sort=-rss | head -15
# Total memory used by all PHP-FPM workers, in MB
ps -ylC php-fpm8.3 --sort:rss | awk 'NR>1 {s+=$8} END {printf "%.0f MB\n", s/1024}'| Column | Means | Worry when |
|---|---|---|
| total | Physical RAM installed | Never |
| used | In use by processes | It approaches total with low available |
| free | Completely untouched | Never: low here is normal and desirable |
| buff/cache | Filesystem cache, reclaimable on demand | Never |
| available | What a new process could actually get | Below about 10 percent of total |
Only the last row is a real signal. Alerting on free produces constant false alarms.
# The out-of-memory killer leaves a record
sudo dmesg -T | grep -i 'killed process'
sudo journalctl -k | grep -i 'out of memory'
# Swap usage per process: heavy swapping is why a server feels frozen
for f in /proc/*/status; do
awk '/^Name|^VmSwap/ {printf "%s ", $2} END {print ""}' "$f" 2>/dev/null
done | grep -v ' 0 kB' | sort -k2 -rn | headThe OOM killer usually picks your database
It targets the process using the most memory, which on a web server is almost always MySQL or MariaDB. The site then fails with a database connection error that looks nothing like a memory problem. Always check dmesg before chasing the connection error itself.
How do I check disk space and find what is using it?
df tells you how full each filesystem is. du tells you which directories are responsible. You need both, and you need to check inodes as well, because a filesystem can refuse writes with plenty of space remaining if it has run out of them.
# Free space per filesystem
df -h
# Inodes: a disk can be 'full' at 40% space used
df -i
# Biggest directories at the top level, sorted
sudo du -h --max-depth=1 / 2>/dev/null | sort -rh | head -15
# Then narrow down
sudo du -h --max-depth=1 /var 2>/dev/null | sort -rh | head
# Biggest individual files anywhere
sudo find / -type f -size +500M -exec ls -lh {} \; 2>/dev/null | awk '{print $5, $9}'
# ncdu is worth installing: an interactive, browsable du
sudo apt install -y ncdu && sudo ncdu /varDeleting a file does not always free the space
If a process still has the file open, the space stays allocated until that process closes it or restarts. This is the classic case of deleting a huge log file and watching df refuse to change. sudo lsof +L1 lists deleted files still held open, along with the process holding each one.
# Log files, the most common cause by far
sudo du -sh /var/log/* | sort -rh | head
# Truncate a huge live log without breaking the writing process
sudo truncate -s 0 /var/log/nginx/access.log
# Old kernels on Debian and Ubuntu
sudo apt autoremove --purge
# Package manager caches
sudo apt clean # Debian / Ubuntu
sudo dnf clean all # RHEL family
# Docker, which quietly accumulates a great deal
docker system df
docker system prune -a --volumes # read what this will delete firsttruncate -s 0, not rm, on a log that is currently being written: rm leaves the space allocated to the open handle.How do I check disk I/O?
When wa is high in top, disk I/O is the constraint. Two tools split the job: iostat shows how busy each device is, and iotop shows which process is responsible.
sudo apt install -y sysstat iotop
# Per-device utilisation, refreshing every 2 seconds
iostat -xz 2
# %util near 100 means the device is saturated
# await is average wait time per request in ms
# Which process is doing the I/O
sudo iotop -o # -o shows only processes actually doing I/O
# Per-process totals, no extra tools needed
sudo grep -H '' /proc/*/io 2>/dev/null | grep read_bytes | sort -t: -k3 -rn | head%util above 90 with a rising await means the storage is the bottleneck, full stop.On a virtual server, %steal in top is worth watching too. It is time your CPU was ready to run but the host gave to somebody else. Consistently above a few percent means the physical machine is oversubscribed, which is not something you can tune your way out of.
What should I check first when a server feels slow?
Work in this order. It takes about a minute and separates the four causes that account for nearly every case.
- 1
uptime. Load against core count. High load with low CPU usage points at I/O or memory rather than computation. - 2
free -h. Readavailable. Low available plus swap activity means the server is thrashing, and everything else you measure will look bad as a consequence. - 3
df -handdf -i. A full disk breaks everything downstream in confusing ways, so rule it out early rather than late. - 4
top, sorted by CPU then by memory. Now you know which process is responsible, which is the only thing that lets you act. - 5The logs for that process. Understanding Linux system logs covers where each service writes and how to follow it.
echo '--- load / cores ---'; uptime; nproc
echo '--- memory ---'; free -h
echo '--- disk ---'; df -h | grep -vE 'tmpfs|udev'
echo '--- inodes ---'; df -i | grep -vE 'tmpfs|udev'
echo '--- top CPU ---'; ps -eo pcpu,pid,user,comm --sort=-pcpu | head -6
echo '--- top RAM ---'; ps -eo rss,pid,user,comm --sort=-rss | head -6
echo '--- OOM kills ---'; sudo dmesg -T | grep -i 'killed process' | tail -5One reading is an anecdote
A single snapshot cannot distinguish a passing spike from a sustained problem. Take three, a few minutes apart, and compare. If you need the answer for something that has already happened, that is what continuous monitoring is for: our dashboard keeps 90 days of per-site CPU and memory, so you can look at the moment it went wrong rather than guessing afterwards. See platform monitoring.
If the process at the top of the list turns out to be PHP, the cause is usually in the application rather than the server. Troubleshooting high CPU and memory on WordPress picks up from there.
Frequently asked questions
What is a good load average on a Linux server?
Anything below your core count. Load 3 on a 4-core machine is healthy; load 3 on a single-core machine means requests are queueing three deep. Divide the load by the output of nproc for the figure that actually means something.
Why does free -h show almost no free memory?
Linux uses spare RAM as filesystem cache because idle memory is wasted memory, and it releases that cache instantly when a process needs it. Read the available column instead, which is what a new process could actually get. Low free with healthy available is normal.
What does wa mean in top?
I/O wait: the percentage of time the CPU was idle because it was waiting for disk. Anything consistently above 10 percent means storage is your bottleneck, and more CPU will not help. Use iostat -xz 2 and iotop -o to find which device and process are responsible.
My disk shows free space but I get "no space left on device". Why?
You have run out of inodes, which are the metadata slots that track individual files. Check with df -i. Millions of small session or cache files exhaust them long before the space runs out. Delete the small files rather than looking for large ones.
I deleted a large log file but df still shows the disk full. Why?
A process still has the file open, so the kernel keeps the space allocated until that process closes it. Find them with sudo lsof +L1, then restart the process holding the handle. In future use truncate -s 0 file.log instead of rm on a live log.
How do I find which process is using the most memory?
ps -eo rss,pid,user,comm --sort=-rss | head sorts by resident memory. In top or htop, press M. Remember that many small workers, such as a PHP-FPM pool, may add up to far more than the single largest process shows.
About G7Cloud Engineering
Articles written by the engineers who build and run G7Cloud: UK managed hosting and the AI Website Builder. We write about what we operate every day: containers, backups, databases, and the small-business websites that run on them.
More about G7Cloud →