Introduction
Monitoring your server’s vital resources like CPU, memory, and disk is crucial for performance, uptime, and system health. While advanced solutions like Zabbix and Prometheus exist, they can be overkill for smaller servers or specific use cases.
In this article, you’ll learn how to create a lightweight monitoring script in Python, which can:
- Collect system metrics (CPU, RAM, Disk)
- Automatically send email alerts when thresholds are exceeded
- Log alerts to a file
- Run silently when everything is fine
It’s perfect for all linux-based systems and uses msmtp to send alert emails via Gmail.
Requirements
To get started, make sure you have:
- Python 3 installed
- The psutil library (for system metrics)
- msmtp installed and configured with Gmail
- Basic knowledge of bash and cron (optional for automation)
Installing Dependencies
Install psutil in a virtual environment (recommended)
sudo apt install python3-venv
python3 -m venv env
source env/bin/activate
pip install psutil
Install and configure msmtp:
sudo apt install msmtp msmtp-mta
Create or edit the ~/.msmtprc file:
defaults
auth on
tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile ~/.msmtp.log
account gmail
host smtp.gmail.com
port 587
from your@gmail.com
user your@gmail.com
password gmail_password
account default : gmail
Don’t forget to secure the password file:
chmod 600 ~/.msmtprc
The Monitoring Script
Below is the Python script that does all the work:
import psutil
import socket
import datetime
import subprocess
# Configuration
TO_EMAIL = "your@gmail.com"
FROM_EMAIL = "your@gmail.com"
CPU_THRESHOLD = 90
RAM_THRESHOLD = 10
DISK_THRESHOLD = 90
# Collect system metrics
def get_metrics():
hostname = socket.gethostname()
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
cpu = psutil.cpu_percent(interval=1)
ram = psutil.virtual_memory()
disk = psutil.disk_usage('/')
return {
"hostname": hostname,
"timestamp": now,
"cpu": cpu,
"ram": ram.percent,
"ram_used": round(ram.used / (1024**3), 2),
"ram_total": round(ram.total / (1024**3), 2),
"disk": disk.percent,
"disk_used": round(disk.used / (1024**3), 2),
"disk_total": round(disk.total / (1024**3), 2)
}
# Build email content
def format_email(metrics):
issues = []
if metrics["cpu"] > CPU_THRESHOLD:
issues.append(f"CPU {metrics['cpu']}%")
if metrics["ram"] > RAM_THRESHOLD:
issues.append(f"RAM {metrics['ram']}%")
if metrics["disk"] > DISK_THRESHOLD:
issues.append(f"Disk {metrics['disk']}%")
if issues:
subject = f"[ALERT] {', '.join(issues)} on {metrics['hostname']}"
else:
subject = f"[INFO] System Stable - {metrics['hostname']}"
message = f"""\
Subject: {subject}
From: Monitoring <{FROM_EMAIL}>
To: {TO_EMAIL}
Date : {metrics['timestamp']}
Server : {metrics['hostname']}
CPU : {metrics['cpu']}% used
RAM : {metrics['ram']}% used ({metrics['ram_used']} GB / {metrics['ram_total']} GB)
Disk : {metrics['disk']}% used ({metrics['disk_used']} GB / {metrics['disk_total']} GB)
"""
return message, bool(issues)
# Send the email using msmtp
def send_email(body):
process = subprocess.Popen(
['msmtp', TO_EMAIL],
stdin=subprocess.PIPE,
stderr=subprocess.PIPE
)
stdout, stderr = process.communicate(input=body.encode())
if process.returncode != 0:
print("Failed to send email:", stderr.decode())
else:
print("Email sent successfully.")
# Log alerts locally
def log_alert(message):
with open("monitoring.log", "a") as log:
log.write(f"[{datetime.datetime.now()}]\n{message}\n{'-'*40}\n")
# Main
if __name__ == "__main__":
metrics = get_metrics()
email_body, alert_needed = format_email(metrics)
if alert_needed:
send_email(email_body)
log_alert(email_body)
else:
print(" System is stable. No alert sent.")
Custom Thresholds
Adjust these values as needed in the configuration section of the script:
CPU_THRESHOLD = 90
RAM_THRESHOLD = 10
DISK_THRESHOLD = 90
For example:
- RAM 85%+ is usually a sign of overload.
- CPU usage above 90% for more than a few seconds can be critical.
- Disk usage near 100% can cause application crashes Running and Testing Make it executable:
chmod +x monitor.py
./monitor.py
You can also schedule it with cron:
crontab -e
Add this to run every 10 minutes:
*/10 * * * * /path/to/monitor.py
Log file output
Each alert is saved in a file named monitoring.log with the timestamp and full details. This helps with auditing and tracking repeated issues over time.
Conclusion
With just a few lines of Python and the power of msmtp, you’ve built a compact monitoring system that:
- Keeps track of key system metrics
- Sends real-time email alerts
- Stores logs for later review
This solution is perfect for home servers, Raspberry Pi setups, low-resource VPSs, or developers who want full control over their monitoring stack.
You can extend it further by adding:
- Load average and uptime
- Service availability checks (e.g., web server, database)
THANK YOU!
Top comments (0)