需求

  1. 每天定时推送服务器流量使用情况,发送到邮箱
  2. 服务器上运行着代理流量等服务,一天下来需要查看流量使用量,推送到邮箱,手机上可登录邮箱查看

效果图

20211226024951.jpg

pushnetworktraffic.PNG

实现步骤

1. 依赖系统 vnstat 工具,读取流量数据
2. Python读取vnstat流量数据,推送到邮箱
3. vnstat提供了,json,xml格式数据
4. 添加计划任务到点执行脚本,实现定时推送消息

安装vnstat

Centos系统

yum install vnstat

Debian系统

apt-get install vnstat

因为vnstat工具以后台运行,来记录保存流量使用情况,所以需要vnstat需要开机自启动
设置vnstat开机自启

systemctl enable vnstat

启动服务

systemctl start vnstat

查看网卡天流量,等五分钟会刷新数据

vnstat -i eth0 -d

Python实现

步骤1.获取系统当天时间

因为需要获取当天流量情况
time.strftime函数
传入值%Y %m %d
%Y=年 %m=月 %d=天

def get_system_time(date):
    date = time.strftime(date)
    return date

步骤2.获取xml格式流量数据

执行如下系统命令,会返回xml格式流量数据

使用正规表达式匹配 来取值

vnstat -i eth0 -d --xml

注意设置要取值得网卡eth0,第六行

def get_data():
    time.strftime("%Y%m%d")
    year = get_system_time('%Y')
    month = get_system_time('%m')
    day = get_system_time('%d')
    system_eval = "vnstat\t-i\teth0\t--xml"
    get_xml = os.popen(system_eval).read()
    #open_file = open('./value.xml','r',encoding='utf-8')
    #get_xml = open_file.read()
    find_file_value = re.findall(r'<date><year>'+year+'</year><month>'+month+'</month><day>'+day+"</day></date><rx>(\w+)</rx><tx>(\w+)</tx></top>",get_xml)
    get_day_data = find_file_value[-1]
    #open_file.close()
    return get_day_data

步骤3.处理流量数据

因为vnstat返回得是Bytes流量值,我们需要MB,GB值,
在计算机操作系统中,存储单位为1024进制
1024Byte(字节)=1KB
1024KB=1MB
1024MB=1GB
1024GB=1TB
1024TB=1PB
用Byte值除1024 得到KB值,以此类推

def print_today_data(company):
    rx_bytes = int(get_data()[0])
    rx_kb = rx_bytes / 1024
    rx_mb = rx_kb / 1024
    rx_gb = rx_mb / 1024

    tx_bytes = int(get_data()[1])
    tx_kb = tx_bytes / 1024
    tx_mb = tx_kb / 1024
    tx_gb = tx_mb / 1024

    if company == "MB":
        return (round(rx_mb,2),round(tx_mb,2))
    elif company == "GB":
        return (round(rx_gb,2),round(tx_gb,2))
    else:
        print("\u8bf7\u8f93\u5165\u5355\u4f4d\uff1a\u006d\u0062\u0020\u6216\u0020\u0067\u0062")

步骤4.获取系统公网IP

https://www.bt.cn/Api/getIpAddress 发送http请求返回系统公网IP

def get_ip_addr():
    get_ip_aip = "https://www.bt.cn/Api/getIpAddress"
    headers = {'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0"}
    get_http_info = urllib.request.Request(url=get_ip_aip,headers=headers)
    run_http = urllib.request.urlopen(get_http_info)
    return run_http.read().decode('utf-8')

步骤5.登录邮箱,发送数据到邮件

QQ邮箱,163邮件等等,支持SMTP SSL邮箱,需要开通此服务,网上教程多

def main():
    print("\u005b\u002b\u005d\t\u6b63\u5728\u8bfb\u53d6\u6570\u636e\u002e\u002e\u002e")

    #填写SMTP邮箱服务器,如下QQ邮箱 SMTP邮箱服务器
    Email_host = 'smtp.qq.com'
    #要登录邮箱用户,QQ邮箱
    from_addr = '[email protected]'
    #邮箱登录密码
    from_passwd = '123456'
    #接收邮件地址
    to_addr = '[email protected]'
    #设置读取单位 GB或者MB
    data_company = "GB"

    format_data = print_today_data(data_company)
    get_all_data =  print_today_data(data_company)[0] + print_today_data(data_company)[1]
    msg = MIMEText("\u670d\u52a1\u5668\u0049\u0050\uff1a"+str(get_ip_addr())+str(get_system_time('\n\n%Y{y}%m{m}%d{d}').format(y="\u5e74", m="\u6708", d="\u53f7"))+"\n\n\u4e0a\u4f20\u6d41\u91cf\uff1a"+str(format_data[0])+data_company+"\n\u4e0b\u8f7d\u6d41\u91cf\uff1a"+str(format_data[1])+data_company+"\n\u4eca\u603b\u6d41\u91cf\uff1a"+str(get_all_data)+data_company)
    msg['Subject'] = "\u6d41\u91cf\u65e5\u5fd7"
    msg["From"] = "运行日志"+"<"+from_addr
    msg["To"] = to_addr
    try:
        Email = smtplib.SMTP_SSL(Email_host,465)
        login = Email.login(from_addr,from_passwd)
    except smtplib.SMTPAuthenticationError as e:
        print("\u005b\u002d\u005d\t\u767b\u5f55\u5931\u8d25\u002e\u53ef\u80fd\u7528\u6237\u6216\u5bc6\u7801\u9519\u8bef")
        pass
    except Exception as e:
        print("\u005b\u002d\u005d\t\u90ae\u7bb1\u670d\u52a1\u5668\u8fde\u63a5\u5931\u8d25")
        pass
    else:
        try:
            Email.sendmail(from_addr, to_addr, msg.as_string())
            Email.quit()
        except UnboundLocalError as e:
            print("\u005b\u002d\u005d\t\u767b\u5f55\u5931\u8d25")
        else:
            print("\u005b\u002b\u005d\t\u90ae\u7bb1\u53d1\u9001\u6210\u529f")

最后完整Python脚本

链接 >> https://www.nstns.com/api/download.php?file=/xs/code/py/pushnetworktraffic.zip

import smtplib
import os
import time
from email.mime.text import MIMEText
import xml
import re
import urllib.request

##Python推送流量使用情况到邮箱
##参考 >> https://www.nstns.com/pushnetworktraffic.html
#Yozz 2021-12.26

def get_system_time(date):
    date = time.strftime(date)
    return date

def get_data():
    time.strftime("%Y%m%d")
    year = get_system_time('%Y')
    month = get_system_time('%m')
    day = get_system_time('%d')
    system_eval = "vnstat\t-i\teth0\t--xml"
    get_xml = os.popen(system_eval).read()
    #open_file = open('./value.xml','r',encoding='utf-8')
    #get_xml = open_file.read()
    find_file_value = re.findall(r'<date><year>'+year+'</year><month>'+month+'</month><day>'+day+"</day></date><rx>(\w+)</rx><tx>(\w+)</tx></top>",get_xml)
    get_day_data = find_file_value[-1]
    #open_file.close()
    return get_day_data

def print_today_data(company):
    rx_bytes = int(get_data()[0])
    rx_kb = rx_bytes / 1024
    rx_mb = rx_kb / 1024
    rx_gb = rx_mb / 1024

    tx_bytes = int(get_data()[1])
    tx_kb = tx_bytes / 1024
    tx_mb = tx_kb / 1024
    tx_gb = tx_mb / 1024

    if company == "MB":
        return (round(rx_mb,2),round(tx_mb,2))
    elif company == "GB":
        return (round(rx_gb,2),round(tx_gb,2))
    else:
        print("\u8bf7\u8f93\u5165\u5355\u4f4d\uff1a\u006d\u0062\u0020\u6216\u0020\u0067\u0062")

def get_ip_addr():
    get_ip_aip = "https://www.bt.cn/Api/getIpAddress"
    headers = {'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0"}
    get_http_info = urllib.request.Request(url=get_ip_aip,headers=headers)
    run_http = urllib.request.urlopen(get_http_info)
    return run_http.read().decode('utf-8')

def main():
    print("\u005b\u002b\u005d\t\u6b63\u5728\u8bfb\u53d6\u6570\u636e\u002e\u002e\u002e")

    #填写SMTP邮箱服务器,如下QQ邮箱 SMTP邮箱服务器
    Email_host = 'smtp.qq.com'
    #要登录邮箱用户
    from_addr = '[email protected]'
    #邮箱登录密码
    from_passwd = '123456'
    #接收邮件地址
    to_addr = '[email protected]'
    #设置读取单位 GB或者MB
    data_company = "GB"

    format_data = print_today_data(data_company)
    get_all_data =  print_today_data(data_company)[0] + print_today_data(data_company)[1]
    msg = MIMEText("\u670d\u52a1\u5668\u0049\u0050\uff1a"+str(get_ip_addr())+str(get_system_time('\n\n%Y{y}%m{m}%d{d}').format(y="\u5e74", m="\u6708", d="\u53f7"))+"\n\n\u4e0a\u4f20\u6d41\u91cf\uff1a"+str(format_data[0])+data_company+"\n\u4e0b\u8f7d\u6d41\u91cf\uff1a"+str(format_data[1])+data_company+"\n\u4eca\u603b\u6d41\u91cf\uff1a"+str(get_all_data)+data_company)
    msg['Subject'] = "\u6d41\u91cf\u65e5\u5fd7"
    msg["From"] = "运行日志"+"<"+from_addr
    msg["To"] = to_addr
    try:
        Email = smtplib.SMTP_SSL(Email_host,465)
        login = Email.login(from_addr,from_passwd)
    except smtplib.SMTPAuthenticationError as e:
        print("\u005b\u002d\u005d\t\u767b\u5f55\u5931\u8d25\u002e\u53ef\u80fd\u7528\u6237\u6216\u5bc6\u7801\u9519\u8bef")
        pass
    except Exception as e:
        print("\u005b\u002d\u005d\t\u90ae\u7bb1\u670d\u52a1\u5668\u8fde\u63a5\u5931\u8d25")
        pass
    else:
        try:
            Email.sendmail(from_addr, to_addr, msg.as_string())
            Email.quit()
        except UnboundLocalError as e:
            print("\u005b\u002d\u005d\t\u767b\u5f55\u5931\u8d25")
        else:
            print("\u005b\u002b\u005d\t\u90ae\u7bb1\u53d1\u9001\u6210\u529f")

if __name__ == '__main__':
    main()
    #获取公网IP
    #print(get_ip_addr())
    #获取系统时间
    #print(get_system_time('%Y{y}%m{m}%d{d}').format(y="\u5e74", m="\u6708", d="\u53f7"))
    #获取总流量单位GB
    #print(print_today_data("GB")[0]+print_today_data("GB")[1])
    #h获取总流量单位MB
    #print(print_today_data("MB")[0]+print_today_data("MB")[1])
    exit()

定时执行

定时去执行脚本,完成定时重启
在Linux下的crontab计划任务软件
末尾添加

sudo vim /etc/crontab

每天第23小时50分执行脚本,推送消息

50 23 * * * root /usr/bin/python3.6 /data/py/pushnetworktraffic.py > /tmp/pushnetworktraffic.log

任务格式

* * * * * user command
分 时 日 月 周 用户 命令
最后修改:2021 年 12 月 26 日
如果觉得我的文章对你有用,请随意赞赏