Monitor Servers with psutil
Monitor servers with psutil — Python for DevOps automation. Learn to track CPU, memory, disk, and network stats with hands-on code.
Focus: monitor servers with psutil
Ever SSHed into a server at 2 AM because a monitoring alert fired, only to find it was a false positive? Or worse, discovered too late that disk filled up and took down your service? psutil is the Python library that gives you direct access to system metrics — CPU, memory, disk, network — so you can write your own lightweight monitoring scripts, detect issues before they snowball, and automate server health checks. This lesson shows you how to monitor servers with psutil, from basic snapshots to a practical monitoring script you can run right away.
The problem this lesson solves
As a DevOps engineer, you depend on monitoring to keep systems healthy. But commercial monitoring tools can be overkill for small fleets, and sometimes you need a custom metric that off-the-shelf agents don't expose. When you need to answer "What's the CPU usage right now?" or "Is disk filling up?" quickly, SSHing into each box and running top or df is slow and error-prone — especially across dozens of servers.
Moreover, monitoring often needs to be proactive — not just reacting to alerts after they fire. You might want to collect metrics periodically, log them, or trigger an action when a threshold is crossed. Doing this manually is impossible at scale.
That's where psutil (Python System and Process Utilities) changes the game. It gives you a clean, Pythonic API to read system statistics without calling external commands like vmstat or iostat — making it trivial to write custom monitoring scripts that fit your exact needs.
Core concept / mental model
Think of psutil as a system health checkup toolkit. When you visit a doctor, they measure your heart rate, blood pressure, temperature — each metric tells you about a different part of your health. Similarly, psutil gives you vital signs for your server:
- CPU — utilization, frequency, core counts
- Memory — physical and virtual RAM usage
- Disk — partition usage and I/O counters
- Network — bytes sent/received, connections
- Processes — list running processes, their CPU and memory footprints
💡 Mental model: You're writing a health monitor for your infrastructure.
psutilis the stethoscope — it gives you the raw readings, and your script decides if the patient (server) needs immediate attention.
The library is cross-platform (Linux, Windows, macOS) and returns data in simple Python structures: float for percentages, namedtuples for detailed stats. That makes it perfect for scripting and automation.
How it works step by step
- Install psutil —
pip install psutil(usually already available; consider adding torequirements.txt). - Import the module —
import psutil. - Get CPU usage —
psutil.cpu_percent(interval=1)returns a float percentage of overall CPU usage. For per-core, usepsutil.cpu_percent(interval=1, percpu=True). - Get memory usage —
psutil.virtual_memory()returns a namedtuple withtotal,available,percent,used, and more.psutil.swap_memory()gives swap stats. - Get disk usage —
psutil.disk_usage('/')returnstotal,used,free,percent. To list all partitions, usepsutil.disk_partitions(). - Get network stats —
psutil.net_io_counters()returnsbytes_sent,bytes_recv, and more. For per-interface, passpernic=True.
Each call is a snapshot — to monitor over time, loop and collect data at intervals.
Hands-on walkthrough
Let's build a simple server health query script and a more advanced monitor that logs and alerts.
1. Quick snapshot script
import psutil
# CPU
print("CPU %:", psutil.cpu_percent(interval=1))
print("CPU cores (physical):", psutil.cpu_count(logical=False))
# Memory
mem = psutil.virtual_memory()
print("Memory total:", mem.total)
print("Memory used:", mem.used)
print("Memory %:", mem.percent)
# Disk
for part in psutil.disk_partitions():
if part.fstype:
usage = psutil.disk_usage(part.mountpoint)
print(f"Disk {part.mountpoint}: {usage.percent}% used")
# Network
net = psutil.net_io_counters()
print("Network bytes sent:", net.bytes_sent)
print("Network bytes recv:", net.bytes_recv)
Expected output (values will vary):
CPU %: 12.4
CPU cores (physical): 8
Memory total: 16759715840
Memory used: 5157879808
Memory %: 30.8
Disk /: 42.1% used
Disk /boot/efi: 11.7% used
Network bytes sent: 1234567890
Network bytes recv: 9876543210
2. Continuous monitor with thresholds
Here we create a loop that checks every 5 seconds and logs a warning if CPU > 80% or disk > 90%:
import psutil
import time
import logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s')
THRESHOLDS = {
'cpu': 80.0,
'disk': 90.0,
'memory': 90.0,
}
while True:
cpu = psutil.cpu_percent(interval=1)
mem = psutil.virtual_memory().percent
disk = psutil.disk_usage('/').percent
if cpu > THRESHOLDS['cpu']:
logging.warning(f"CPU high: {cpu}%")
if mem > THRESHOLDS['memory']:
logging.warning(f"Memory high: {mem}%")
if disk > THRESHOLDS['disk']:
logging.warning(f"Disk high: {disk}%")
logging.info(f"Health: CPU={cpu}%, MEM={mem}%, DISK={disk}%")
time.sleep(5)
Expected output (when CPU is high):
2023-10-05 14:22:01,123 INFO Health: CPU=12.0%, MEM=30.0%, DISK=42.0%
2023-10-05 14:22:06,456 INFO Health: CPU=85.0%, MEM=30.0%, DISK=42.0%
2023-10-05 14:22:06,457 WARNING CPU high: 85.0%
💡 Pro tip: For production, consider logging to a file or sending alerts via webhook (e.g., Slack) instead of just printing.
3. Collect process-level details
To understand what's consuming resources, you can iterate over processes:
import psutil
for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent']):
try:
info = proc.info
if info['cpu_percent'] > 1.0 or info['memory_percent'] > 1.0:
print(f"PID {info['pid']} — {info['name']}: CPU {info['cpu_percent']}%, MEM {info['memory_percent']}%")
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
Expected output (truncated):
PID 1234 — python3: CPU 2.5%, MEM 1.2%
PID 5678 — chrome: CPU 5.1%, MEM 3.4%
Compare options / when to choose what
When monitoring servers, you have several approaches:
| Approach | Pros | Cons | Best for |
|---|---|---|---|
psutil + custom script |
Lightweight, full control, no extra services | You maintain the script | Small fleets, quick checks, custom metrics |
top/htop via SSH |
No setup, human-friendly | Not automatable, interactive only | Manual debugging |
| Cloud provider metrics (e.g., AWS CloudWatch) | Managed, historical, alerts | Vendor lock‑in, cost | Production at scale |
| Prometheus + Grafana | Powerful, open source, auto-discovery | Need to run agents and stack | Heavy monitoring, long-term storage |
When to choose what:
- Use
psutilfor ad‑hoc checks, custom lightweight monitors, or when you need to embed system stats in a Python app. - Use
topfor a quick look during an SSH session. - Use full monitoring stacks for critical production environments with alerting and dashboards.
A common pattern is to use psutil to collect and push metrics to a central system (e.g., to CloudWatch or Prometheus via Pushgateway).
Troubleshooting & edge cases
psutil.cpu_percentreturns 0.0 on first call: By default,cpu_percentreturns the CPU usage since the last call. The first call returns 0.0 because there's no previous sample. Fix: Call it withinterval=1or call it twice — once a dummy call, then use the second.- Permission errors when listing processes: Some processes (like system services) require elevated privileges to inspect. Fix: Catch
psutil.AccessDeniedand continue, or run withsudoif you need full info. - Different disk mount points: On some systems,
/might not be the only mount. Fix: Iteratepsutil.disk_partitions()and skip those with no mount point or fstype. - Network counters are cumulative:
net_io_countersshows bytes since boot. To get current rate, sample twice and compute difference over time. - Memory usage high but swap low: High memory percentage might not mean a problem — cache is often reclaimed. Look at
availableinstead ofused.
What you learned & what's next
You now understand the core idea behind monitoring servers with psutil: it provides a Pythonic API to read system metrics — CPU, memory, disk, and network — enabling you to write custom monitoring scripts. You completed a practical exercise that queries these metrics and logs alerts when thresholds are exceeded. You also saw how to list process-level usage and compared psutil to other monitoring solutions.
Next step: In the next lesson, you'll learn how to integrate these metrics into a broader infrastructure automation workflow — perhaps sending alerts to a messaging service or storing them in a time-series database. With psutil, you now have the building block to create production-ready monitoring agents.
Practice recap
Write a script that logs CPU, memory, and disk usage to a file every 10 seconds, and if CPU > 70%, also logs a warning. Run it for a minute with varied load (e.g., open a browser) and inspect the log. Next, modify the script to send an alert via a webhook when a threshold is breached — that's a solid foundation for an internal monitoring tool.
Common mistakes
- Calling
psutil.cpu_percent()without a prior call — it returns 0.0 on the first invocation because it's a delta since last call. Useinterval=1to force sampling. - Ignoring
psutil.AccessDeniedwhen iterating processes — always wrap in try/except and skip inaccessible entries. - Using
disk_usage('/')on systems where/is not the only mount point — iteratedisk_partitions()instead. - Treating
memory_percentas absolute truth — at high usage, OS caching inflates the number; checkavailablememory instead.
Variations
- Use
psutil.cpu_times()andpsutil.cpu_times_percent()for detailed user/system idle breakdowns. - Integrate with a metrics library like
prometheus_clientto expose psutil data as Prometheus metrics. - Use
psutil.net_io_counters()to compute network throughput by measuring deltas between samples.
Real-world use cases
- A small startup has 5 cloud VMs and uses a cron‑scheduled psutil script to push CPU and memory usage to CloudWatch via boto3.
- A DevOps team writes a Python health check that uses psutil to verify disk space remains above 20% before deploying new features.
- An on‑premise server farm uses a psutil‑based agent to stream CPU, memory, and network stats to a central Prometheus instance for dashboarding.
Key takeaways
- psutil gives Pythonic access to CPU, memory, disk, and network metrics without shelling out to system commands.
- Always handle first‑call CPU percentages and permission errors to make scripts robust.
- Use threshold‑based logging to create lightweight monitoring alerts.
- Combine psutil with process iteration to pinpoint resource hogs.
- Choose psutil for custom, lightweight monitoring; use full stacks for production‑scale needs.
- Sample network counters twice to compute transfer rates.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.