DEV Community

Rubin Mosepinza
Rubin Mosepinza

Posted on

How to Build a Lightweight System Monitoring and Alert Script on linux Using Python and MSMTP

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
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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.")

Enter fullscreen mode Exit fullscreen mode

Custom Thresholds
Adjust these values as needed in the configuration section of the script:

CPU_THRESHOLD = 90
RAM_THRESHOLD = 10
DISK_THRESHOLD = 90

Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

You can also schedule it with cron:
crontab -e
Add this to run every 10 minutes:
*/10 * * * * /path/to/monitor.py

Image description

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)