zabbix主动上报的python脚本

跨平台Zabbix监控脚本:Python实现系统性能数据上报

📌 文章导读

本文分享一个基于Python的跨平台监控脚本,通过psutil库采集系统性能数据(CPU、内存、磁盘、网络、TCP连接数),并使用zabbix_sender将数据上报到Zabbix Server。脚本已在Linux和Windows平台验证可用,适合需要自定义监控项的场景。

📦 一、环境依赖与兼容性说明

1.1 Python版本选择

Python版本Windows 2008兼容性说明
Python 3.6+ ⚠️ 需要VC2015运行库 需提前安装SP1补丁和VC2015 redistributable
Python 2.7 ✅ 直接可用 无需额外运行库,推荐在老系统使用

1.2 依赖库安装

# 安装psutil库(跨平台系统信息采集)
pip install psutil

# 如果使用国内镜像加速
pip install psutil -i https://pypi.tuna.tsinghua.edu.cn/simple

🐍 二、完整脚本代码

脚本实现了以下监控项的采集与上报:

  • CPU使用率 (CPU_usage_rate)
  • 内存使用率 (Memory_usage_rate)
  • 磁盘使用率 (Disk_usage_rate)
  • TCP连接数 (TCP_Estab)
  • 网络入流量 (Network_In)
  • 网络出流量 (Network_Out)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# =============================================
# 功能:跨平台系统监控数据采集,通过zabbix_sender上报
# 作者:GuoYabin
# 依赖:psutil库 (pip install psutil)
# 平台:Linux / Windows
# =============================================

import os, sys, time, psutil

# 获取当前系统平台
def my_system():
    return sys.platform

# 根据系统返回zabbix_sender路径
def zabbix_bin():
    if my_system() == 'win32':
        return 'C:\\zabbix\\zabbix_sender.exe'
    else:
        return '/usr/local/zabbix/bin/zabbix_sender'

# 获取内网IP和网卡名称(匹配10.1网段)
def my_ip():
    ip_dict = psutil.net_if_addrs()
    for nic, addrs in ip_dict.items():
        for addr in addrs:
            # 判断是否为内网IP(10.1开头)
            if addr.address.startswith('10.1'):
                return nic, addr.address
    return None, None

# 获取内存使用率(百分比)
def my_mem():
    return psutil.virtual_memory().percent

# 获取CPU使用率(0.5秒采样)
def my_cpu():
    return psutil.cpu_percent(interval=0.5)

# 获取ESTABLISHED状态的TCP连接数(跨平台)
def my_tcp():
    if my_system() == 'win32':
        # Windows:使用netstat命令统计ESTABLISHED连接
        result = os.popen('netstat -n | find /C "ESTAB"').read()
        return int(result.strip())
    else:
        # Linux:使用ss命令解析ESTABLISHED数量
        # ss -s 输出第4行包含ESTAB数量
        result = os.popen("ss -s | grep -o '[0-9]*[1-9]' | awk 'NR==4'").read()
        return int(result.strip())

# 获取磁盘使用率(可自定义分区)
def my_disk():
    if my_system() == 'win32':
        # Windows默认监控第二个分区(D盘)
        panfu = psutil.disk_partitions()[1].device
    else:
        # Linux监控/usr/local分区
        panfu = '/usr/local'
    return psutil.disk_usage(panfu).percent

# 获取网络流量(1秒内入站/出站字节数)
def my_network():
    # 获取主监控网卡名称
    nic_name, _ = my_ip()
    
    # 第一次采样
    counters = psutil.net_io_counters(pernic=True)[nic_name]
    old_out = counters.bytes_sent
    old_in = counters.bytes_recv
    
    # 间隔1秒(可调整)
    time.sleep(1)
    
    # 第二次采样
    counters = psutil.net_io_counters(pernic=True)[nic_name]
    new_out = counters.bytes_sent
    new_in = counters.bytes_recv
    
    # 计算差值(字节/秒)
    return new_out - old_out, new_in - new_in

# 主程序入口
if __name__ == '__main__':
    # Zabbix服务器地址
    report_url = '10.1.2.61'
    
    # 获取本机IP作为zabbix主机名
    _, host_ip = my_ip()
    
    # 监控项键值列表
    zabbix_keys = [
        'CPU_usage_rate',
        'Network_In',
        'Network_Out',
        'TCP_Estab',
        'Disk_usage_rate',
        'Memory_usage_rate'
    ]
    
    # 采集监控数据(注意顺序与keys一致)
    out_bytes, in_bytes = my_network()
    zabbix_values = [
        my_cpu(),
        in_bytes,
        out_bytes,
        my_tcp(),
        my_disk(),
        my_mem()
    ]
    
    # 循环调用zabbix_sender上报数据
    for i in range(6):
        cmd = f"{zabbix_bin()} -z {report_url} -s {host_ip} -k {zabbix_keys[i]} -o {zabbix_values[i]}"
        os.system(cmd)
        # 可选:添加短暂延时避免发送过快
        # time.sleep(0.1)

🔍 三、核心函数解析

3.1 平台识别与路径管理

# my_system() 返回系统类型
- 'win32':Windows系统
- 'linux':Linux系统
- 'darwin':macOS系统

# zabbix_bin() 根据不同系统返回zabbix_sender路径
- Windows默认:C:\zabbix\zabbix_sender.exe
- Linux默认:/usr/local/zabbix/bin/zabbix_sender

3.2 网络流量采集的优化思考

原代码中time.sleep(1)会导致主线程暂停,对于需要快速执行的场景不够理想。以下是几种优化思路:

方案优点缺点
定时任务中连续调用两次 脚本退出快,不占用进程 需要外部记录上一次的值
使用多线程异步采集 可以同时采集多个指标 实现复杂,可能引入竞态条件
接受1秒延迟(当前方案) 简单可靠,代码清晰 每分钟采集会损失1秒

3.3 TCP连接数的跨平台实现

# Windows实现:使用netstat命令统计
netstat -n | find /C "ESTAB"

# Linux实现:使用ss命令解析ESTABLISHED数量
# ss -s 输出示例:
# Total: 1234 (kernel 1234)
# TCP:   567 (estab 89, closed 234, orphaned 0, synrecv 0, timewait 234/0), ports 0
ss -s | grep -o '[0-9]*[1-9]' | awk 'NR==4'

⚙️ 四、部署与配置

4.1 文件部署

# Linux部署
将脚本保存为 /usr/local/bin/zabbix_monitor.py
chmod +x /usr/local/bin/zabbix_monitor.py

# Windows部署
将脚本保存为 C:\zabbix\zabbix_monitor.py
确保 zabbix_sender.exe 在 C:\zabbix\ 目录下

4.2 添加到计划任务

# Linux crontab(每分钟执行)
*/1 * * * * /usr/bin/python /usr/local/bin/zabbix_monitor.py >> /var/log/zabbix_monitor.log 2>&1

# Windows 任务计划程序
创建基本任务 → 触发器设置为每分钟一次 → 操作选择启动程序
程序或脚本: C:\Python27\python.exe
参数: C:\zabbix\zabbix_monitor.py

📈 五、扩展建议

1. 增加Load Average监控(Linux)

import os
def my_loadavg():
    # 方法1:使用os.getloadavg()(Python 3.3+)
    load1, load5, load15 = os.getloadavg()
    return load1
    
    # 方法2:解析uptime命令(兼容老版本)
    # result = os.popen("uptime").read()
    # 用正则提取第一个浮点数

2. 增加异常处理

try:
    cpu = my_cpu()
except Exception as e:
    print(f"CPU采集失败: {e}")
    cpu = -1  # 使用-1标识异常

3. 优化zabbix_sender调用

# 使用subprocess模块替代os.system,可以获得返回值
import subprocess
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if result.returncode != 0:
    print(f"发送失败: {result.stderr}")

📝 六、常见问题排查

问题现象可能原因解决方案
ImportError: No module named psutil psutil库未安装 执行 pip install psutil
zabbix_sender: command not found 路径配置错误 检查zabbix_bin()返回的路径是否正确
网络流量始终为0 网卡名称匹配失败 检查my_ip()返回的网卡名是否正确

✅ 总结

这个脚本通过psutil库实现了跨平台的系统监控数据采集,配合zabbix_sender上报到Zabbix Server,解决了传统使用命令行解析的繁琐问题。脚本结构清晰,易于扩展,可根据实际需求增加新的监控项(如进程数、IO负载等)。

—— 如果觉得本文对你有帮助,欢迎收藏转发~

posted @ 2017-04-25 16:58  一起走过的路  阅读(1549)  评论(0)    收藏  举报