做运维的朋友应该都有过这种经历:大半夜睡得正香,手机突然被客户连环call吵醒——服务器挂了。等你睡眼惺忪地爬起来连上VPS一看,磁盘满了,或者内存爆了,但日志里什么都没留下。这种「事后才知道」的被动局面,真的让人很头疼。
其实很多服务器故障都是有预兆的,比如CPU负载持续飙升、内存使用率缓慢爬升、磁盘空间一点点被日志吃掉。如果我们能提前设置一个监控脚本,在资源超过阈值时第一时间收到告警,就能把很多问题扼杀在摇篮里。今天我就分享一个我用了很久的轻量级监控脚本,用Python写的,逻辑简单,注释详细,拿过去改改就能直接用。
为什么不用现成的监控工具?
你可能会说,Prometheus、Zabbix、Grafana这些不都是专业的监控方案吗?没错,它们功能强大,但部署和运维成本也不低。对于一台个人博客、小型企业应用或者学生党手里的低配VPS来说,杀鸡用牛刀反而累赘。而且这些工具本身也要吃内存,在1G内存的小机器上跑一套监控全家桶,那真是雪上加霜。
我的观点是:能用脚本解决的事,就别上重型框架。一个Python脚本,配合crontab定时任务,就能覆盖90%的日常监控需求。剩下的10%等你真的业务大了,再考虑上专业监控也不迟。
脚本能干什么?
- 每分钟记录一次CPU平均负载(1分钟、5分钟、15分钟)
- 记录内存使用率(已用/总量)
- 记录根分区磁盘使用率
- 超过阈值时通过邮件发送告警
- 所有日志追加写入一个CSV文件,方便事后回看趋势
先看完整代码,我用的Python 3,不需要安装任何第三方库,标准库就够。
完整监控脚本(Python版)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
server_monitor.py - 简单服务器监控脚本
功能:记录CPU负载、内存、磁盘,超阈值发送邮件告警
用法:配合crontab每分钟执行一次
"""
import os
import time
import datetime
import smtplib
from email.mime.text import MIMEText
# ========== 配置区域 ==========
CPU_THRESHOLD = 2.0 # 1分钟负载超过此值告警(按单核算,4核机器建议4.0)
MEM_THRESHOLD = 85.0 # 内存使用率超过85%告警
DISK_THRESHOLD = 85.0 # 磁盘使用率超过85%告警
LOG_FILE = "/var/log/server_monitor.csv" # 日志文件路径
# 邮件告警配置(用QQ邮箱或163邮箱都行,需要开启SMTP)
SMTP_HOST = "smtp.qq.com"
SMTP_PORT = 465
SMTP_USER = "你的邮箱@qq.com"
SMTP_PASS = "你的授权码" # 不是登录密码!是邮箱设置里生成的授权码
ALERT_TO = "接收告警的邮箱@example.com"
# ============================
def get_cpu_load():
"""读取 /proc/loadavg,获取1/5/15分钟平均负载"""
with open("/proc/loadavg", "r") as f:
parts = f.read().split()
# 前三个字段分别是1分钟、5分钟、15分钟负载
return float(parts[0]), float(parts[1]), float(parts[2])
def get_memory_usage():
"""从 /proc/meminfo 获取内存信息,计算使用率"""
with open("/proc/meminfo", "r") as f:
lines = f.readlines()
mem_info = {}
for line in lines:
key, value = line.split(":", 1)
# 单位是kB,去掉末尾的 " kB"
mem_info[key] = int(value.strip().split()[0])
total = mem_info["MemTotal"]
available = mem_info["MemAvailable"]
used_percent = (total - available) / total * 100
return used_percent
def get_disk_usage():
"""使用 os.statvfs 获取根分区磁盘使用率"""
st = os.statvfs("/")
total = st.f_blocks * st.f_frsize
free = st.f_bavail * st.f_frsize
used_percent = (total - free) / total * 100
return used_percent
def send_alert(subject, body):
"""发送邮件告警(使用SMTP SSL)"""
msg = MIMEText(body, "plain", "utf-8")
msg["Subject"] = subject
msg["From"] = SMTP_USER
msg["To"] = ALERT_TO
try:
with smtplib.SMTP_SSL(SMTP_HOST, SMTP_PORT) as server:
server.login(SMTP_USER, SMTP_PASS)
server.sendmail(SMTP_USER, [ALERT_TO], msg.as_string())
print("[告警] 邮件发送成功")
except Exception as e:
print(f"[告警] 邮件发送失败: {e}")
def log_to_csv(data):
"""将一行数据追加写入CSV文件"""
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
line = f"{timestamp},{data['load1']},{data['load5']},{data['load15']},{data['mem']:.1f},{data['disk']:.1f}\n"
# 如果文件不存在,先写表头
if not os.path.exists(LOG_FILE):
with open(LOG_FILE, "w") as f:
f.write("time,load1,load5,load15,mem_percent,disk_percent\n")
with open(LOG_FILE, "a") as f:
f.write(line)
def main():
# 采集数据
load1, load5, load15 = get_cpu_load()
mem_percent = get_memory_usage()
disk_percent = get_disk_usage()
data = {
"load1": load1,
"load5": load5,
"load15": load15,
"mem": mem_percent,
"disk": disk_percent
}
# 写入日志
log_to_csv(data)
# 检查阈值,超了就告警
problems = []
if load1 > CPU_THRESHOLD:
problems.append(f"CPU负载过高: {load1} (阈值 {CPU_THRESHOLD})")
if mem_percent > MEM_THRESHOLD:
problems.append(f"内存使用率: {mem_percent:.1f}% (阈值 {MEM_THRESHOLD}%)")
if disk_percent > DISK_THRESHOLD:
problems.append(f"磁盘使用率: {disk_percent:.1f}% (阈值 {DISK_THRESHOLD}%)")
if problems:
body = "\n".join(problems)
body += f"\n\n时间: {datetime.datetime.now()}"
send_alert(f"[服务器告警] {datetime.datetime.now().strftime('%m-%d %H:%M')}", body)
else:
print(f"[OK] 负载:{load1} 内存:{mem_percent:.1f}% 磁盘:{disk_percent:.1f}%")
if __name__ == "__main__":
main()
怎么部署?三步搞定
第一步:把脚本保存到 /usr/local/bin/server_monitor.py,然后给它执行权限:
chmod +x /usr/local/bin/server_monitor.py第二步:配置邮件SMTP。我这里用的QQ邮箱,你需要登录邮箱网页版,在「设置 → 账户」里开启SMTP服务,生成一个授权码。把授权码填到脚本的 SMTP_PASS 变量里。如果你用其他邮箱,对应修改 SMTP_HOST 和端口即可。
第三步:添加crontab定时任务,每分钟执行一次:
crontab -e加入下面一行
- /usr/bin/python3 /usr/local/bin/server_monitor.py >> /var/log/server_monitor.log 2>&1
保存后,脚本就会每分钟跑一次了。你可以先手动执行一次看看输出:
python3 /usr/local/bin/server_monitor.py
如果看到类似 [OK] 负载:0.05 内存:42.3% 磁盘:67.1% 的输出,就说明一切正常。
实际使用中的小经验
我在一台雨云服务器上跑了这个脚本半年多,确实帮我提前发现过几次问题。有一次磁盘使用率连续三天缓慢爬升,从70%涨到80%,我通过CSV日志看到趋势,一查发现是Nginx的access log没做切割,单日志文件已经好几个G了。还好发现得早,不然再过一周磁盘就要满了。
这里分享几个调优经验:
- CPU阈值怎么定?看你的CPU核数。如果机器是2核,负载超过2.0基本就跑满了;如果是4核,阈值可以设到3.5左右。一般建议设为核数的70%~80%。
- 告警邮件容易轰炸。资源一直超阈值的话,每分钟一封邮件会烦死人。你可以改成连续3次超阈值才告警,或者用Shell脚本配合简单状态文件实现。我这里为了保持代码简单,没有加防抖,实际部署时建议加上。
- CSV日志要定期清理。每分钟一行,一个月大约4万行,才几百KB,问题不大。但如果你要保留一年,建议写个Logrotate规则。
如果不想用Python,Bash也能写
有的朋友可能不喜欢装Python(虽然现在基本都有),那用Bash写个精简版也完全OK。核心就是读取 /proc/loadavg 和 free、df 命令的输出。不过Bash处理浮点运算比较麻烦,需要借助 awk 或 bc。我个人还是推荐Python,可读性和扩展性都更好。
总结:监控脚本是运维的「安全网」
这个脚本虽然简单,但胜在轻量、透明、可控。它就像一个尽职的哨兵,每分钟帮你盯着服务器的关键指标,出了异常立刻给你发微信(通过邮件转微信提醒)。你可以在这个基础上继续扩展,比如添加网络流量监控、进程存活检测、甚至接入钉钉/企业微信机器人告警。
最后啰嗦一句:监控不是目的,预防才是。脚本只是帮你发现问题,真正解决问题还是要靠平时的维护习惯,比如定期清理日志、合理规划磁盘分区、及时升级内核等等。希望这个脚本能让你少熬夜、多睡好觉。如果你有更好玩的监控思路,欢迎在评论区交流!
顺便提一句,如果你还没服务器练手,可以看看雨云服务器,价格挺实惠的,新用户用优惠码 aabh 还能省点钱,拿来跑这种监控脚本或者搭个小网站都很合适。
评论区: