Lightweight Linux Web Server Monitoring Tools with Email Alerts: DIY Python Script vs Ready Solutions


2 views

When maintaining internal web servers, basic uptime monitoring with alerting is essential yet often overlooked. The requirements are straightforward:

  • Simple URL-based checks (HTTP/HTTPS)
  • Email notification on failure
  • Internal network operation (no SaaS dependencies)
  • Minimal resource footprint

Monit provides comprehensive monitoring but requires more configuration than just a URL:

check host example with address 192.168.1.10
    if failed port 80 protocol http
    then alert

Nagios Core offers powerful monitoring but has significant overhead for simple checks:

define service {
    host_name               web-server
    service_description     HTTP Check
    check_command           check_http!-H example.local -w 2 -c 3
    contacts                admin-email
}

For minimal requirements, a custom Python script often proves most effective. Here's an enhanced version of the original solution with these improvements:

  • Timeout handling
  • SMTP authentication support
  • Configurable check intervals
#!/usr/bin/env python3
import requests
import smtplib
import time
from email.mime.text import MIMEText

CONFIG = {
    'url': 'http://internal-server.local',
    'check_interval': 300,
    'smtp': {
        'host': 'smtp.example.com',
        'port': 587,
        'user': 'alert@example.com',
        'password': 'secret',
        'sender': 'monitor@example.com',
        'recipients': ['admin@example.com']
    }
}

def check_server():
    try:
        response = requests.get(CONFIG['url'], timeout=10)
        return response.status_code == 200
    except:
        return False

def send_alert():
    msg = MIMEText(f"Server {CONFIG['url']} is down!")
    msg['Subject'] = f"Server Alert: {CONFIG['url']}"
    msg['From'] = CONFIG['smtp']['sender']
    msg['To'] = ", ".join(CONFIG['smtp']['recipients'])

    with smtplib.SMTP(CONFIG['smtp']['host'], CONFIG['smtp']['port']) as server:
        server.starttls()
        server.login(CONFIG['smtp']['user'], CONFIG['smtp']['password'])
        server.send_message(msg)

if __name__ == '__main__':
    while True:
        if not check_server():
            send_alert()
        time.sleep(CONFIG['check_interval'])

For production use, consider these enhancements:

  1. Run as a systemd service for automatic restart
  2. Add logging to track historical availability
  3. Implement exponential backoff for alerts
  4. Include SSL certificate expiration monitoring

The Python solution excels when:

  • You need absolute minimal dependencies
  • The monitoring logic must be customized
  • Internal security policies restrict third-party tools

Pre-built tools become preferable when:

  • You need historical data visualization
  • Multiple team members require access
  • Monitoring requirements may expand

When maintaining internal web servers on Linux, having a reliable monitoring solution is crucial. Many existing tools are either too complex for simple uptime checks or require external services. What you need is a lightweight, self-contained solution that can run locally and send email alerts when issues occur.

For basic monitoring, you can use existing Linux tools with some scripting:

#!/bin/bash
if curl --output /dev/null --silent --head --fail "http://yourserver"; then
    echo "Server is up"
else
    echo "Server is down" | mail -s "Server Alert" admin@example.com
fi

Several excellent open-source options exist for this purpose:

  • Monit: Lightweight and highly configurable
  • Nagios Core: More feature-rich but still suitable for internal networks
  • Zabbix: Includes web monitoring capabilities

Here's an enhanced version of a Python monitoring script that handles multiple servers:

import smtplib
import requests
from email.mime.text import MIMEText

servers = ["http://server1", "http://server2"]
sender = "monitor@yourdomain.com"
receivers = ["admin@yourdomain.com"]

def check_server(url):
    try:
        response = requests.get(url, timeout=5)
        return response.status_code == 200
    except:
        return False

def send_alert(server):
    msg = MIMEText(f"Server {server} is down!")
    msg['Subject'] = f"Server Alert: {server}"
    msg['From'] = sender
    msg['To'] = ", ".join(receivers)
    
    with smtplib.SMTP('localhost') as server:
        server.sendmail(sender, receivers, msg.as_string())

for server in servers:
    if not check_server(server):
        send_alert(server)

When setting up your monitoring:

  • Run checks at reasonable intervals (e.g., every 1-5 minutes)
  • Implement alert throttling to avoid email floods
  • Consider adding basic authentication support if needed
  • Log monitoring results for historical analysis

To run your monitoring script regularly, add this to crontab:

*/5 * * * * /usr/bin/python3 /path/to/monitor.py