ESC

Start typing to search across invoices, services, domains, tickets, and more...

Search... Ctrl+K
Linux Server

Linux Server Monitoring: Check CPU, Memory, Disk I/O and Bandwidth Usage (top, iostat, iftop, vnstat)

7 steps 15 min read 5 views 0
On this page

When a site slows down, SSH lags or traffic suddenly spikes, the first job is to find the bottleneck. This guide gives you a practical Linux server monitoring toolkit: top/htop for CPU and processes, free for memory, iostat and iotop for disk I/O, iftop, nload and vnstat for bandwidth usage, ss to find who holds connections, and a small cron script for alerts. It applies to VPS and dedicated servers running Debian/Ubuntu or Rocky Linux/AlmaLinux.

Step 1: Install the Monitoring Tools

top, free and ss are built in; the rest need installing, and on Rocky/AlmaLinux you must enable EPEL first. The examples use eth0 as the interface name, so check the real name with ip -br addr.

# Debian / Ubuntu
apt install -y htop sysstat iotop iftop nload vnstat nethogs
# Rocky Linux / AlmaLinux (most tools are in EPEL)
dnf install -y epel-release
dnf install -y htop sysstat iotop iftop nload vnstat nethogs

ip -br addr          # find your network interface name (eth0, ens3, ...)

Step 2: Check CPU Usage and Load with top and htop

The three load average numbers are the 1, 5 and 15 minute averages; if they stay above the number of cores, the server cannot keep up. In top focus on three fields: high us means your applications burn CPU; high wa means the CPU is waiting for disk, so look at I/O next; on a VPS, persistently high st (steal) indicates contention on the host, and you can open a ticket so our team can check.

nproc                # number of CPU cores
uptime               # load average for 1, 5 and 15 minutes
top                  # 1 = per-core view, P = sort by CPU, M = sort by memory, q = quit
htop                 # F6 to choose the sort column, F9 to send a signal
ps aux --sort=-%cpu | head -n 10

Step 3: Check Memory Usage and OOM Kills

Judge memory pressure by the available column of free -h, not the free column, because Linux uses idle memory for cache. If si/so in vmstat stay above zero, the system is swapping heavily. When processes vanish without a trace, check dmesg for the OOM killer. If memory is short, add swap (see our swap tutorial) or upgrade the plan.

free -h
vmstat 1 5                                   # si/so > 0 continuously = swapping
ps aux --sort=-%mem | head -n 10
dmesg -T | grep -iE "out of memory|killed process"
journalctl -k --since "1 day ago" | grep -i oom

Step 4: Track Down Disk I/O and Disk Space Problems

In iostat, %util near 100 % together with rising await means the disk is saturated. iotop then shows which process reads or writes the most, typically a database, log writer or backup job. Once sysstat is enabled it records every 10 minutes, so sar can show you what happened earlier. For space issues see our disk-space-full tutorial.

iostat -xz 1 5        # watch %util, r_await / w_await, rkB/s and wkB/s
iotop -oPa            # only processes doing I/O, accumulated totals
df -h                 # space usage
df -i                 # inode usage

# Keep history with sysstat, then read it with sar
systemctl enable --now sysstat
sar -u                # CPU today
sar -d -p             # disks today

Step 5: View Live Bandwidth and Traffic Totals

nload shows live inbound and outbound rates for an interface; iftop lists traffic per remote IP so you can see who is downloading heavily; nethogs breaks it down by process. vnstat keeps daily and monthly totals in the background, which is handy for checking bandwidth or traffic usage. Unexplained outbound traffic can mean the server has been compromised and is attacking others.

ip -s link show eth0          # total RX/TX bytes since boot
nload eth0                    # live in/out graph
iftop -i eth0 -nNP            # live traffic per remote host and port
nethogs eth0                  # live traffic per process

systemctl enable --now vnstat
vnstat -i eth0 -l             # live rate
vnstat -d                     # daily totals
vnstat -m                     # monthly totals

Step 6: Find Connection and Bandwidth Sources with ss

ss is the faster replacement for netstat. The command below counts established connections per remote IP, which quickly exposes aggressive crawlers or HTTP flood sources that you can then block with the firewall or Fail2ban.

ss -s                                              # connection summary
ss -tunp | head -n 30                              # connections with process names
ss -lntup                                          # listening ports

# Top 10 remote IPs by number of established TCP connections
ss -Htn state established | awk '{sub(/:[0-9]+$/,"",$4); print $4}' \
  | sort | uniq -c | sort -rn | head -n 10

# Connections to your web server only
ss -Htn state established '( sport = :443 )' | wc -l

Step 7: Simple Alerts with a Cron Script

If you do not run Zabbix or Prometheus yet, a short script can check load, available memory and disk usage every five minutes, log any breach and push it to a webhook such as a Telegram bot, Slack or Discord (adjust the JSON body to the platform).

cat > /usr/local/bin/check-health.sh <<'EOF'
#!/bin/bash
LOAD_MAX=$(nproc)          # alert when 1-min load > number of cores
MEM_MIN_MB=200             # alert when available memory < 200 MB
DISK_MAX=90                # alert when a filesystem is >= 90 % full
WEBHOOK="https://hooks.example.com/your-webhook"
HOST=$(hostname)
MSG=""

LOAD=$(cut -d' ' -f1 /proc/loadavg)
if awk -v l="$LOAD" -v m="$LOAD_MAX" 'BEGIN{exit !(l>m)}'; then
  MSG+="load $LOAD > $LOAD_MAX; "
fi

AVAIL=$(free -m | awk '/^Mem:/{print $7}')
if [ "$AVAIL" -lt "$MEM_MIN_MB" ]; then MSG+="available memory ${AVAIL}MB; "; fi

while read -r USE MNT; do
  if [ "${USE%\%}" -ge "$DISK_MAX" ]; then MSG+="disk $MNT at $USE; "; fi
done < <(df -P -x tmpfs -x devtmpfs | awk 'NR>1{print $5, $6}')

if [ -n "$MSG" ]; then
  echo "$(date '+%F %T') $HOST $MSG" >> /var/log/health-alert.log
  curl -s -m 10 -H 'Content-Type: application/json' \
    -d "{\"text\":\"[$HOST] $MSG\"}" "$WEBHOOK" > /dev/null
fi
EOF
chmod +x /usr/local/bin/check-health.sh
/usr/local/bin/check-health.sh; tail /var/log/health-alert.log

# Run every 5 minutes: crontab -e
*/5 * * * * /usr/local/bin/check-health.sh
A script is only a safety net. For busy servers deploy Netdata, Zabbix or Prometheus with Grafana, and add an external uptime check from another server so you are alerted even when the whole machine is down.

FAQ

CPU usage is low in top but the load is high?

Load also counts processes waiting on disk I/O (state D). Check the wa value and iostat; a busy disk or slow network storage is the usual cause.

vnstat says "no data available"?

A fresh vnstat has nothing recorded yet; wait a few minutes with the service running. Also confirm that your interface appears in vnstat --iflist.

How do I find the process using the most bandwidth?

Run nethogs eth0 to see live traffic per process, then ss -tunp to see where that process is connected, and decide whether it is legitimate.

Still stuck after following these steps? Open a support ticket and the IMIDC 24/7 technical team will help. Include the server IP, OS version, the commands you ran and the full error output so we can pinpoint the issue faster.

Was this answer helpful?

Related Tutorials