“Psutil + Flask开发Linux /Windows系统监控”的版本间的差异

来自CloudWiki
跳转至: 导航搜索
(创建页面,内容为“==简介== psutil 是一个跨平台库(http://pythonhosted.org/psutil)能够获取到系统运行的进程和系统利用率(包括CPU、内存、磁盘、网…”)
 
技术准备
 
(未显示同一用户的12个中间版本)
第2行: 第2行:
 
psutil 是一个跨平台库(http://pythonhosted.org/psutil)能够获取到系统运行的进程和系统利用率(包括CPU、内存、磁盘、网络等)信息。主要用来做系统监控,性能分析,进程管理。支持 Linux、Mac OS、Windows 系统。
 
psutil 是一个跨平台库(http://pythonhosted.org/psutil)能够获取到系统运行的进程和系统利用率(包括CPU、内存、磁盘、网络等)信息。主要用来做系统监控,性能分析,进程管理。支持 Linux、Mac OS、Windows 系统。
  
本文以 psutil 模块获取系统信息开发一个监控 Windows 系统的平台。
+
本文以 psutil 模块获取系统信息开发一个监控 Windows /linux系统的平台。
  
 
==技术选择==
 
==技术选择==
  
*监控的系统是 Windows 系统
+
*监控的系统是 Windows /linux系统
  
 
*监控系统模块选择 psutil 模块
 
*监控系统模块选择 psutil 模块
第12行: 第12行:
 
*Web 框架选择的是 Flask 框架
 
*Web 框架选择的是 Flask 框架
  
*前端 UI 选择的是 Bootstrap UI
 
 
*动态可视化图表选择 Pyecharts 模块
 
  
 
==技术准备==
 
==技术准备==
 +
===安装 Flask===
 +
[[Python:安装Flask]]
  
 
===安装 psutil===
 
===安装 psutil===
 +
windows/centos7:
  
pip3 install psutil
+
pip3 install psutil
  
===安装 Flask、pyecharts、Bootstrap===
+
centos8:
  
Flask 的教程是在公众号文章:Web 开发 Flask 介绍
+
[[Centos 8 配置yum源]]、[[Centos 8安装psutil]]
  
Pyecharts 的教程在公众号文章:Python 图表利器 pyecharts,按照官网 (http://pyecharts.org/#/zh-cn/web_flask) 文档整合 Flask 框架,并使用定时全量更新图表。
+
==获取系统信息==
 +
===初始化===
 +
app.py:
  
Bootstrap 是一个 前端的 Web UI,官网地址是 (https://v4.bootcss.com)
+
<nowiki>
 +
 
 +
import psutil
 +
import os, signal
 +
from random import randrange
  
 +
from flask import Flask, render_template, jsonify, request
 +
import time
  
 +
app = Flask(__name__, static_folder="templates")
  
==获取系统信息==
+
cpu_percent_dict = {}
===CPU信息===
+
net_io_dict = {'net_io_time':[], 'net_io_sent': [], 'net_io_recv': [], 'pre_sent': 0, 'pre_recv': 0, 'len': -1}
通过 psutil 获取 CPU 信息
+
disk_dict = {'disk_time':[], 'write_bytes': [], 'read_bytes': [], 'pre_write_bytes': 0, 'pre_read_bytes': 0, 'len': -1}
 +
 
 +
cpu_percent_dict = {}</nowiki>
 +
 
 +
===网页模板===
 +
templates/list.html:
  
 
  <nowiki>
 
  <nowiki>
>>> import psutil
+
<!DOCTYPE html>
+
<html lang="zh-CN">
+
  <head>
# 获取当前 CPU 的利用率
+
    <meta charset="utf-8">
>>> psutil.cpu_percent()
+
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
53.8
+
    <meta name="viewport" content="width=device-width, initial-scale=1">
+
    <title>基于psutil的系统监控工具</title>
+
 
# 获取当前 CPU 的用户/系统/空闲时间
+
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
>>> psutil.cpu_times()
+
  </head>
scputimes(user=197483.49, nice=0.0, system=114213.01, idle=1942295.68)
+
 
 
 
# 1/5/15 分钟之内的 CPU 负载
 
>>> psutil.getloadavg()
 
(7.865234375, 5.1826171875, 4.37353515625)
 
 
 
# CPU 逻辑个数
 
>>> psutil.cpu_count()
 
4
 
 
 
# CPU 物理个数
 
>>> psutil.cpu_count(logical=False)
 
2</nowiki>
 
  
在监控平台上每 2 秒请求 url 获取 CPU 负载,并动态显示图表:
+
<body>
 +
    <h1>{{title}}</h1>
 +
    <table id="customers" class="table table-striped">
 +
    <tr>
 +
      <th>监测项</th>
 +
      <th>数值</th>
 +
    </tr>
 +
 
 +
    {% for key, value in my_dict.items() %}
 +
    <tr>
 +
      <td>{{ key }}</td>
 +
      <td>{{ value}}</td>
 +
    </tr>
 +
    {% endfor %}
 +
    </table>
 +
</body>
 +
</html></nowiki>
 +
 
 +
===CPU信息===
 +
通过 psutil 获取 CPU 信息
  
 
  <nowiki>
 
  <nowiki>
cpu_percent_dict = {}
+
@app.route("/cpu")
 
def cpu():
 
def cpu():
     # 当前时间
+
     for i in range(1,6):
    now = time.strftime('%H:%M:%S', time.localtime(time.time()))
+
        # 当前时间
    #  CPU 负载
+
        now = time.strftime('%H:%M:%S', time.localtime(time.time()))
    cpu_percent = psutil.cpu_percent()
+
        #  CPU 负载
    cpu_percent_dict[now] = cpu_percent
+
        cpu_percent = psutil.cpu_percent()
+
        cpu_percent_dict[now] = cpu_percent
+
        time.sleep(0.3)
 +
 
 
     # 保持在图表中 10 个数据
 
     # 保持在图表中 10 个数据
 
     if len(cpu_percent_dict.keys()) == 11:
 
     if len(cpu_percent_dict.keys()) == 11:
 
         cpu_percent_dict.pop(list(cpu_percent_dict.keys())[0])
 
         cpu_percent_dict.pop(list(cpu_percent_dict.keys())[0])
+
 
+
     return render_template('list.html', title="CPU使用情况",my_dict=cpu_percent_dict)
def cpu_line() -> Line:
+
 
     cpu()
+
if __name__ == '__main__':#程序入口
    # 全量更新 pyecharts 图表
+
     #app.run()#让应用运行在本地服务器上。
    c = (
+
     app.run(debug=True,host='0.0.0.0') #允许任意网址访问本站
        Line()
+
</nowiki>
            .add_xaxis(list(cpu_percent_dict.keys()))
+
 
            .add_yaxis('', list(cpu_percent_dict.values()), areastyle_opts=opts.AreaStyleOpts(opacity=0.5))
+
[[文件:python2022052702.png|600px]]
            .set_global_opts(title_opts=opts.TitleOpts(title = now + "CPU负载",pos_left = "center"),
 
                            yaxis_opts=opts.AxisOpts(min_=0,max_=100,split_number=10,type_="value", name='%'))
 
     )
 
     return c
 
 
 
@app.route("/cpu")
 
def get_cpu_chart():
 
    c = cpu_line()
 
    return c.dump_options_with_quotes()</nowiki>
 
  
 
===内存===
 
===内存===
 
  <nowiki>
 
  <nowiki>
 +
@app.route("/memory")
 
def memory():
 
def memory():
 
     memory = psutil.virtual_memory()
 
     memory = psutil.virtual_memory()
 
     swap = psutil.swap_memory()
 
     swap = psutil.swap_memory()
     return memory.total, memory.used, \
+
     sys={}
          memory.free, swap.total, swap.used, swap.free, memory.percent
+
    sys['mem_total']= memory.total
 +
    sys['mem_used']= memory.used
 +
    sys['mem_free']= memory.free
 +
    sys['swap_total']=swap.total
 +
    sys['swap_used']=swap.used
 +
    sys['swap_free']=swap.free
 +
    sys['memory_percent']= memory.percent
 +
 
 +
    return render_template('list.html', title="内存使用情况",my_dict=sys)
  
  
def memory_liquid() -> Gauge:
 
    mtotal, mused, mfree, stotal, sused, sfree, mpercent = memory()
 
    c = (
 
        Gauge()
 
            .add("", [("", mpercent)])
 
            .set_global_opts(title_opts=opts.TitleOpts(title="内存负载", pos_left = "center"))
 
    )
 
    return mtotal, mused, mfree, stotal, sused, sfree, c
 
  
 +
</nowiki>
  
@app.route("/memory")
+
效果:
def get_memory_chart():
 
    mtotal, mused, mfree, stotal, sused, sfree, c = memory_liquid()
 
    return jsonify({'mtotal': mtotal, 'mused': mused, 'mfree': mfree, 'stotal': stotal, 'sused': sused, 'sfree': sfree, 'liquid': c.dump_options_with_quotes()})
 
  
</nowiki>
+
[[文件:python2022052701.png|600px]]
  
  
第130行: 第138行:
 
===磁盘===
 
===磁盘===
 
通过 psutil 获取磁盘大小、分区、使用率和磁盘IO
 
通过 psutil 获取磁盘大小、分区、使用率和磁盘IO
 
在监控平台上每 2 秒请求 url 获取磁盘信息,并动态显示图表
 
 
<nowiki>
 
def disk():
 
    disk_usage = psutil.disk_usage('/')
 
    disk_used = 0
 
    # 磁盘已使用大小 = 每个分区的总和
 
    partitions = psutil.disk_partitions()
 
    for partition in partitions:
 
        partition_disk_usage = psutil.disk_usage(partition[1])
 
        disk_used = partition_disk_usage.used + disk_used
 
 
    now = time.strftime('%H:%M:%S', time.localtime(time.time()))
 
    count = psutil.disk_io_counters()
 
    read_bytes = count.read_bytes
 
    write_bytes = count.write_bytes
 
 
    # 第一次请求
 
    if disk_dict['len'] == -1:
 
        disk_dict['pre_write_bytes'] = write_bytes
 
        disk_dict['pre_read_bytes'] = read_bytes
 
        disk_dict['len'] = 0
 
        return disk_usage.total, disk_used, disk_usage.free
 
 
    # 当前速率=现在写入/读取的总字节-前一次请求写入/读取的总字节
 
    disk_dict['write_bytes'].append((write_bytes - disk_dict['pre_write_bytes'])/1024)
 
    disk_dict['read_bytes'].append((read_bytes - disk_dict['pre_read_bytes'])/ 1024)
 
    disk_dict['disk_time'].append(now)
 
    disk_dict['len'] = disk_dict['len'] + 1
 
 
    # 把现在写入/读取的总字节放入前一个请求的变量中
 
    disk_dict['pre_write_bytes'] = write_bytes
 
    disk_dict['pre_read_bytes'] = read_bytes
 
 
    # 保持在图表中 50 个数据
 
    if disk_dict['len'] == 51:
 
        disk_dict['write_bytes'].pop(0)
 
        disk_dict['read_bytes'].pop(0)
 
        disk_dict['disk_time'].pop(0)
 
        disk_dict['len'] = disk_dict['len'] - 1
 
 
    return disk_usage.total, disk_used, disk_usage.free
 
 
 
def disk_line() -> Line:
 
    total, used, free = disk()
 
 
    c = (
 
        Line(init_opts=opts.InitOpts(width="1680px", height="800px"))
 
        .add_xaxis(xaxis_data=disk_dict['disk_time'])
 
        .add_yaxis(
 
            series_name="写入数据",
 
            y_axis=disk_dict['write_bytes'],
 
            areastyle_opts=opts.AreaStyleOpts(opacity=0.5),
 
            linestyle_opts=opts.LineStyleOpts(),
 
            label_opts=opts.LabelOpts(is_show=False),
 
        )
 
        .add_yaxis(
 
            series_name="读取数据",
 
            y_axis=disk_dict['read_bytes'],
 
            yaxis_index=1,
 
            areastyle_opts=opts.AreaStyleOpts(opacity=0.5),
 
            linestyle_opts=opts.LineStyleOpts(),
 
            label_opts=opts.LabelOpts(is_show=False),
 
        )
 
        .extend_axis(
 
            yaxis=opts.AxisOpts(
 
                name_location="start",
 
                type_="value",
 
                is_inverse=True,
 
                axistick_opts=opts.AxisTickOpts(is_show=True),
 
                splitline_opts=opts.SplitLineOpts(is_show=True),
 
                name='KB/2S'
 
            )
 
        )
 
        .set_global_opts(
 
            title_opts=opts.TitleOpts(
 
                title="磁盘IO",
 
                pos_left="center",
 
                pos_top="top",
 
            ),
 
            tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross"),
 
            legend_opts=opts.LegendOpts(pos_left="left"),
 
            xaxis_opts=opts.AxisOpts(type_="category", boundary_gap=False),
 
            yaxis_opts=opts.AxisOpts(type_="value", name='KB/2S'),
 
        )
 
        .set_series_opts(
 
            axisline_opts=opts.AxisLineOpts(),
 
        )
 
    )
 
 
    return total, used, free, c
 
 
@app.route("/disk")
 
def get_disk_chart():
 
    total, used, free, c = disk_line()
 
    return jsonify({'total': total, 'used': used, 'free': free, 'line': c.dump_options_with_quotes()})</nowiki>
 
  
  
第234行: 第144行:
  
 
通过 psutil 获取网络接口和网络连接的信息
 
通过 psutil 获取网络接口和网络连接的信息
 
在监控平台上每 2 秒请求 url 获取网卡IO,并动态显示图表
 
 
<nowiki>
 
def net_io():
 
    now = time.strftime('%H:%M:%S', time.localtime(time.time()))
 
    # 获取网络信息
 
    count = psutil.net_io_counters()
 
    g_sent = count.bytes_sent
 
    g_recv = count.bytes_recv
 
 
    # 第一次请求
 
    if net_io_dict['len'] == -1:
 
        net_io_dict['pre_sent'] = g_sent
 
        net_io_dict['pre_recv'] = g_recv
 
        net_io_dict['len'] = 0
 
        return
 
 
    # 当前网络发送/接收的字节速率 = 现在网络发送/接收的总字节 - 前一次请求网络发送/接收的总字节
 
    net_io_dict['net_io_sent'].append(g_sent - net_io_dict['pre_sent'])
 
    net_io_dict['net_io_recv'].append(g_recv - net_io_dict['pre_recv'])
 
    net_io_dict['net_io_time'].append(now)
 
    net_io_dict['len'] = net_io_dict['len'] + 1
 
 
    net_io_dict['pre_sent'] = g_sent
 
    net_io_dict['pre_recv'] = g_recv
 
 
    # 保持在图表中 10 个数据
 
    if net_io_dict['len'] == 11:
 
        net_io_dict['net_io_sent'].pop(0)
 
        net_io_dict['net_io_recv'].pop(0)
 
        net_io_dict['net_io_time'].pop(0)
 
        net_io_dict['len'] = net_io_dict['len'] - 1
 
 
 
def net_io_line() -> Line:
 
    net_io()
 
 
    c = (
 
    Line()
 
    .add_xaxis(net_io_dict['net_io_time'])
 
    .add_yaxis("发送字节数", net_io_dict['net_io_sent'], is_smooth=True)
 
    .add_yaxis("接收字节数", net_io_dict['net_io_recv'], is_smooth=True)
 
    .set_series_opts(
 
        areastyle_opts=opts.AreaStyleOpts(opacity=0.5),
 
        label_opts=opts.LabelOpts(is_show=False),
 
    )
 
    .set_global_opts(
 
        title_opts=opts.TitleOpts(title="网卡IO", pos_left = "center"),
 
        xaxis_opts=opts.AxisOpts(
 
            axistick_opts=opts.AxisTickOpts(is_align_with_label=True),
 
            is_scale=False,
 
            boundary_gap=False,
 
        ),
 
        yaxis_opts=opts.AxisOpts(type_="value", name='B/2S'),
 
        legend_opts=opts.LegendOpts(pos_left="left"),
 
    ))
 
    return c
 
</nowiki>
 
 
===进程===
 
通过 psutil 可以获取所有进程的信息
 
 
<nowiki>
 
# 所有进程的 pid
 
>>> psutil.pids()
 
[0, 1, 134, 135, 138, 139, 140, 141, 144, 145, 147, 152, ..., 30400, 97792]
 
 
 
# 单个进程
 
>>> p = psutil.Process(30400)
 
 
 
# 名称
 
>>> p.name()
 
'pycharm'
 
 
 
# 使用内存负载
 
>>> p.memory_percent()
 
12.838459014892578
 
 
 
# 启动时间
 
>>> p.create_time()
 
1587029962.493182
 
 
 
# 路径
 
>>> p.exe()
 
'/Applications/PyCharm.app/Contents/MacOS/pycharm'
 
 
 
# 状态
 
>>> p.status()
 
'running'
 
 
 
# 用户名
 
>>> p.username()
 
'imeng'
 
 
 
# 内存信息
 
>>> p.memory_info()
 
pmem(rss=1093005312, vms=9914318848, pfaults=7813313, pageins=8448)</nowiki>
 
 
<nowiki>
 
def process():
 
    result = []
 
    process_list = []
 
    pid = psutil.pids()
 
    for k, i in enumerate(pid):
 
        try:
 
            proc = psutil.Process(i)
 
            ctime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(proc.create_time()))
 
            process_list.append((str(i), proc.name(), proc.cpu_percent(), proc.memory_percent(), ctime))
 
        except psutil.AccessDenied:
 
            pass
 
        except psutil.NoSuchProcess:
 
            pass
 
        except SystemError:
 
            pass
 
 
        process_list.sort(key=process_sort, reverse=True)
 
    for i in process_list:
 
        result.append({'PID': i[0], 'name': i[1], 'cpu': i[2], 'mem': "%.2f%%"%i[3], 'ctime': i[4]})
 
  
  
    return jsonify({'list': result})
 
  
def process_sort(elem):
 
    return elem[3]
 
 
@app.route("/process")
 
def get_process_tab():
 
    c = process()
 
    return c
 
 
@app.route("/delprocess")
 
def del_process():
 
    pid = request.args.get("pid")
 
    os.kill(int(pid), signal.SIGKILL)
 
    return jsonify({'status': 'OK'})
 
 
</nowiki>
 
 
==代码==
 
==代码==
 
===app.py===
 
===app.py===
 
  <nowiki>
 
  <nowiki>
 +
import psutil
 
import os, signal
 
import os, signal
 
from random import randrange
 
from random import randrange
  
 
from flask import Flask, render_template, jsonify, request
 
from flask import Flask, render_template, jsonify, request
 
from pyecharts import options as opts
 
from pyecharts.charts import Bar, Line, Liquid, Gauge, Grid
 
import pyecharts.options as opts
 
 
import time
 
import time
import psutil
 
  
 
app = Flask(__name__, static_folder="templates")
 
app = Flask(__name__, static_folder="templates")
第400行: 第163行:
 
disk_dict = {'disk_time':[], 'write_bytes': [], 'read_bytes': [], 'pre_write_bytes': 0, 'pre_read_bytes': 0, 'len': -1}
 
disk_dict = {'disk_time':[], 'write_bytes': [], 'read_bytes': [], 'pre_write_bytes': 0, 'pre_read_bytes': 0, 'len': -1}
  
 +
cpu_percent_dict = {}
 +
 +
@app.route("/cpu")
 
def cpu():
 
def cpu():
     now = time.strftime('%H:%M:%S', time.localtime(time.time()))
+
     for i in range(1,6):
    cpu_percent = psutil.cpu_percent()
+
        # 当前时间
    cpu_percent_dict[now] = cpu_percent
+
        now = time.strftime('%H:%M:%S', time.localtime(time.time()))
 +
        #  CPU 负载
 +
        cpu_percent = psutil.cpu_percent()
 +
        cpu_percent_dict[now] = cpu_percent
 +
        time.sleep(0.3)
 +
 
 
     # 保持在图表中 10 个数据
 
     # 保持在图表中 10 个数据
 
     if len(cpu_percent_dict.keys()) == 11:
 
     if len(cpu_percent_dict.keys()) == 11:
 
         cpu_percent_dict.pop(list(cpu_percent_dict.keys())[0])
 
         cpu_percent_dict.pop(list(cpu_percent_dict.keys())[0])
  
 +
    return render_template('list.html', title="CPU使用情况",my_dict=cpu_percent_dict)
  
def cpu_line() -> Line:
+
@app.route("/memory")
    now = time.strftime('%Y年%m月%d日的', time.localtime(time.time()))
 
    cpu()
 
    c = (
 
        Line()
 
            .add_xaxis(list(cpu_percent_dict.keys()))
 
            .add_yaxis('', list(cpu_percent_dict.values()), areastyle_opts=opts.AreaStyleOpts(opacity=0.5))
 
            .set_global_opts(title_opts=opts.TitleOpts(title = now + "CPU负载",pos_left = "center"),
 
                            yaxis_opts=opts.AxisOpts(min_=0,max_=100,split_number=10,type_="value", name='%'))
 
    )
 
    return c
 
 
 
 
def memory():
 
def memory():
 
     memory = psutil.virtual_memory()
 
     memory = psutil.virtual_memory()
 
     swap = psutil.swap_memory()
 
     swap = psutil.swap_memory()
     return memory.total, memory.used, \
+
     sys={}
          memory.free, swap.total, swap.used, swap.free, memory.percent
+
    sys['mem_total']= memory.total
 +
    sys['mem_used']= memory.used
 +
    sys['mem_free']= memory.free
 +
    sys['swap_total']=swap.total
 +
    sys['swap_used']=swap.used
 +
    sys['swap_free']=swap.free
 +
    sys['memory_percent']= memory.percent
  
 +
    return render_template('list.html', title="内存使用情况",my_dict=sys)
  
def memory_liquid() -> Gauge:
+
if __name__ == '__main__':#程序入口
    mtotal, mused, mfree, stotal, sused, sfree, mpercent = memory()
+
     #app.run()#让应用运行在本地服务器上。
    c = (
+
     app.run(debug=True,host='0.0.0.0') #允许任意网址访问本站
        Gauge()
 
            .add("", [("", mpercent)])
 
            .set_global_opts(title_opts=opts.TitleOpts(title="内存负载", pos_left = "center"))
 
    )
 
    return mtotal, mused, mfree, stotal, sused, sfree, c
 
 
 
 
 
 
 
def net_io():
 
    now = time.strftime('%H:%M:%S', time.localtime(time.time()))
 
    # 获取网络信息
 
    count = psutil.net_io_counters()
 
    g_sent = count.bytes_sent
 
    g_recv = count.bytes_recv
 
 
 
     # 第一次请求
 
    if net_io_dict['len'] == -1:
 
        net_io_dict['pre_sent'] = g_sent
 
        net_io_dict['pre_recv'] = g_recv
 
        net_io_dict['len'] = 0
 
        return
 
 
 
    # 当前网络发送/接收的字节速率 = 现在网络发送/接收的总字节 - 前一次请求网络发送/接收的总字节
 
    net_io_dict['net_io_sent'].append(g_sent - net_io_dict['pre_sent'])
 
    net_io_dict['net_io_recv'].append(g_recv - net_io_dict['pre_recv'])
 
    net_io_dict['net_io_time'].append(now)
 
    net_io_dict['len'] = net_io_dict['len'] + 1
 
 
 
    net_io_dict['pre_sent'] = g_sent
 
    net_io_dict['pre_recv'] = g_recv
 
 
 
    # 保持在图表中 10 个数据
 
     if net_io_dict['len'] == 11:
 
        net_io_dict['net_io_sent'].pop(0)
 
        net_io_dict['net_io_recv'].pop(0)
 
        net_io_dict['net_io_time'].pop(0)
 
        net_io_dict['len'] = net_io_dict['len'] - 1
 
 
 
 
 
def net_io_line() -> Line:
 
    net_io()
 
 
 
    c = (
 
    Line()
 
    .add_xaxis(net_io_dict['net_io_time'])
 
    .add_yaxis("发送字节数", net_io_dict['net_io_sent'], is_smooth=True)
 
    .add_yaxis("接收字节数", net_io_dict['net_io_recv'], is_smooth=True)
 
    .set_series_opts(
 
        areastyle_opts=opts.AreaStyleOpts(opacity=0.5),
 
        label_opts=opts.LabelOpts(is_show=False),
 
    )
 
    .set_global_opts(
 
        title_opts=opts.TitleOpts(title="网卡IO", pos_left = "center"),
 
        xaxis_opts=opts.AxisOpts(
 
            axistick_opts=opts.AxisTickOpts(is_align_with_label=True),
 
            is_scale=False,
 
            boundary_gap=False,
 
        ),
 
        yaxis_opts=opts.AxisOpts(type_="value", name='B/2S'),
 
        legend_opts=opts.LegendOpts(pos_left="left"),
 
    ))
 
    return c
 
 
 
 
 
def process():
 
    result = []
 
    process_list = []
 
    pid = psutil.pids()
 
    for k, i in enumerate(pid):
 
        try:
 
            proc = psutil.Process(i)
 
            ctime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(proc.create_time()))
 
            process_list.append((str(i), proc.name(), proc.cpu_percent(), proc.memory_percent(), ctime))
 
        except psutil.AccessDenied:
 
            pass
 
        except psutil.NoSuchProcess:
 
            pass
 
        except SystemError:
 
            pass
 
 
 
        process_list.sort(key=process_sort, reverse=True)
 
    for i in process_list:
 
        result.append({'PID': i[0], 'name': i[1], 'cpu': i[2], 'mem': "%.2f%%"%i[3], 'ctime': i[4]})
 
 
 
 
 
    return jsonify({'list': result})
 
 
 
def process_sort(elem):
 
    return elem[3]
 
 
 
 
 
def disk():
 
    disk_usage = psutil.disk_usage('/')
 
    disk_used = 0
 
    # 磁盘已使用大小 = 每个分区的总和
 
    partitions = psutil.disk_partitions()
 
    for partition in partitions:
 
        partition_disk_usage = psutil.disk_usage(partition[1])
 
        disk_used = partition_disk_usage.used + disk_used
 
 
 
    now = time.strftime('%H:%M:%S', time.localtime(time.time()))
 
    count = psutil.disk_io_counters()
 
    read_bytes = count.read_bytes
 
    write_bytes = count.write_bytes
 
 
 
    # 第一次请求
 
    if disk_dict['len'] == -1:
 
        disk_dict['pre_write_bytes'] = write_bytes
 
        disk_dict['pre_read_bytes'] = read_bytes
 
        disk_dict['len'] = 0
 
        return disk_usage.total, disk_used, disk_usage.free
 
 
 
    # 当前速率=现在写入/读取的总字节-前一次请求写入/读取的总字节
 
    disk_dict['write_bytes'].append((write_bytes - disk_dict['pre_write_bytes'])/1024)
 
    disk_dict['read_bytes'].append((read_bytes - disk_dict['pre_read_bytes'])/ 1024)
 
    disk_dict['disk_time'].append(now)
 
    disk_dict['len'] = disk_dict['len'] + 1
 
 
 
    # 把现在写入/读取的总字节放入前一个请求的变量中
 
    disk_dict['pre_write_bytes'] = write_bytes
 
    disk_dict['pre_read_bytes'] = read_bytes
 
 
 
    # 保持在图表中 50 个数据
 
    if disk_dict['len'] == 51:
 
        disk_dict['write_bytes'].pop(0)
 
        disk_dict['read_bytes'].pop(0)
 
        disk_dict['disk_time'].pop(0)
 
        disk_dict['len'] = disk_dict['len'] - 1
 
 
 
    return disk_usage.total, disk_used, disk_usage.free
 
 
 
 
 
def disk_line() -> Line:
 
    total, used, free = disk()
 
 
 
    c = (
 
        Line(init_opts=opts.InitOpts(width="1680px", height="800px"))
 
        .add_xaxis(xaxis_data=disk_dict['disk_time'])
 
        .add_yaxis(
 
            series_name="写入数据",
 
            y_axis=disk_dict['write_bytes'],
 
            areastyle_opts=opts.AreaStyleOpts(opacity=0.5),
 
            linestyle_opts=opts.LineStyleOpts(),
 
            label_opts=opts.LabelOpts(is_show=False),
 
        )
 
        .add_yaxis(
 
            series_name="读取数据",
 
            y_axis=disk_dict['read_bytes'],
 
            yaxis_index=1,
 
            areastyle_opts=opts.AreaStyleOpts(opacity=0.5),
 
            linestyle_opts=opts.LineStyleOpts(),
 
            label_opts=opts.LabelOpts(is_show=False),
 
        )
 
        .extend_axis(
 
            yaxis=opts.AxisOpts(
 
                name_location="start",
 
                type_="value",
 
                is_inverse=True,
 
                axistick_opts=opts.AxisTickOpts(is_show=True),
 
                splitline_opts=opts.SplitLineOpts(is_show=True),
 
                name='KB/2S'
 
            )
 
        )
 
        .set_global_opts(
 
            title_opts=opts.TitleOpts(
 
                title="磁盘IO",
 
                pos_left="center",
 
                pos_top="top",
 
            ),
 
            tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross"),
 
            legend_opts=opts.LegendOpts(pos_left="left"),
 
            xaxis_opts=opts.AxisOpts(type_="category", boundary_gap=False),
 
            yaxis_opts=opts.AxisOpts(type_="value", name='KB/2S'),
 
        )
 
        .set_series_opts(
 
            axisline_opts=opts.AxisLineOpts(),
 
        )
 
    )
 
 
 
    return total, used, free, c
 
 
 
@app.route("/")
 
def index():
 
    return render_template("index.html")
 
 
 
 
 
@app.route("/cpu")
 
def get_cpu_chart():
 
    c = cpu_line()
 
    return c.dump_options_with_quotes()
 
 
 
@app.route("/memory")
 
def get_memory_chart():
 
    mtotal, mused, mfree, stotal, sused, sfree, c = memory_liquid()
 
    return jsonify({'mtotal': mtotal, 'mused': mused, 'mfree': mfree, 'stotal': stotal, 'sused': sused, 'sfree': sfree, 'liquid': c.dump_options_with_quotes()})
 
 
 
 
 
@app.route("/netio")
 
def get_net_io_chart():
 
    c = net_io_line()
 
    return c.dump_options_with_quotes()
 
 
 
@app.route("/process")
 
def get_process_tab():
 
    c = process()
 
    return c
 
 
 
@app.route("/delprocess")
 
def del_process():
 
    pid = request.args.get("pid")
 
    os.kill(int(pid), signal.SIGKILL)
 
    return jsonify({'status': 'OK'})
 
 
 
@app.route("/disk")
 
def get_disk_chart():
 
    total, used, free, c = disk_line()
 
    return jsonify({'total': total, 'used': used, 'free': free, 'line': c.dump_options_with_quotes()})
 
 
 
if __name__ == "__main__":
 
    app.run()
 
  
 
</nowiki>
 
</nowiki>
  
===templates/index.html===
+
===templates/list.html===
 +
templates/list.html:
  
 
  <nowiki>
 
  <nowiki>
第667行: 第216行:
 
     <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
 
     <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
 
   </head>
 
   </head>
  <body>
 
  
  
 +
<body>
 +
    <h1>{{title}}</h1>
 +
    <table id="customers" class="table table-striped">
 +
    <tr>
 +
      <th>监测项</th>
 +
      <th>数值</th>
 +
    </tr>
  
     <div class="container" style="padding-top: 100px">
+
     {% for key, value in my_dict.items() %}
        <div class="row user-list">
+
    <tr>
        <div class="col-sm-12 user" style="">
+
      <td>{{ key }}</td>
            <div id="alert" class="alert alert-success" role="alert" style="margin: auto;left: 0;right: 0;display: none;position: fixed;width: 50%;text-align: center;">删除成功</div>
+
      <td>{{ value}}</td>
        </div>
+
    </tr>
        </div>
+
    {% endfor %}
        <div class="row user-list">
+
    </table>
        <div class="col-sm-12 user">
+
</body></nowiki>
            <div>
 
              <ul class="nav nav-tabs" role="tablist">
 
                <li role="presentation" class="active"><a href="#cpuTab" aria-controls="cpuTab" role="tab" data-toggle="tab">CPU</a></li>
 
                <li role="presentation"><a href="#memoryTab" aria-controls="memoryTab" role="tab" data-toggle="tab">内存</a></li>
 
                  <li role="presentation"><a href="#diskTab" aria-controls="diskTab" role="tab" data-toggle="tab">磁盘</a></li>
 
                <li role="presentation"><a href="#netioTab" aria-controls="netioTab" role="tab" data-toggle="tab">网卡</a></li>
 
                <li role="presentation"><a href="#processTab" aria-controls="processTab" role="tab" data-toggle="tab">进程</a></li>
 
              </ul>
 
  
              <div class="tab-content">
+
==效果==
                <div role="tabpanel" class="tab-pane active" id="cpuTab">
+
[[文件:python2022052702.png|600px]]
                    <div id="cpu" style="width:800px; height:300px;padding-top: 40px;margin-left: auto;margin-right: auto"></div>
 
                </div>
 
                <div role="tabpanel" class="tab-pane" id="memoryTab">
 
                    <div class="row user-list">
 
                        <div class="col-sm-5 user" style="">
 
                            <ul class="list-group" style="padding-left:200px;padding-top:50px">
 
                              <li class="list-group-item list-group-item-success">内存大小:<span class="badge" id="mtotal"></span></li>
 
                              <li class="list-group-item list-group-item-info">内存已使用大小:<span class="badge" id="mused"></span></li>
 
                              <li class="list-group-item list-group-item-warning">内存剩余大小:<span class="badge" id="mfree"></span></li>
 
                                <li class="list-group-item list-group-item-success">交换区大小:<span class="badge" id="stotal"></span></li>
 
                              <li class="list-group-item list-group-item-info">交换区已使用大小:<span class="badge" id="sused"></span></li>
 
                              <li class="list-group-item list-group-item-warning">交换区剩余大小:<span class="badge" id="sfree"></span></li>
 
                            </ul>
 
                        </div>
 
                        <div class="col-sm-7 user" style="">
 
                            <div id="memory" style="width:800px; height:300px;padding-top: 40px;margin-left: -100px;margin-right: auto"></div>
 
                        </div>
 
                    </div>
 
                </div>
 
                <div role="tabpanel" class="tab-pane" id="netioTab">
 
                    <div class="row user-list">
 
                        <div class="col-sm-12 user" style="">
 
                            <div id="netio" style="width:800px; height:300px;padding-top: 40px;margin-left: auto;margin-right: auto"></div>
 
                        </div>
 
                    </div>
 
                </div>
 
                <div role="tabpanel" class="tab-pane" id="processTab">
 
                    <table class="table table-hover" style="height:100px;padding-top: 40px;margin-left: auto;margin-right: auto">
 
                      <thead>
 
                        <tr>
 
                          <th>PID</th>
 
                          <th>程序</th>
 
                          <th>占用内存</th>
 
                          <th>创建时间</th>
 
                          <th>强行停止</th>
 
                        </tr>
 
                      </thead>
 
                      <tbody id="tbody">
 
                      </tbody>
 
                    </table>
 
                </div>
 
                <div role="tabpanel" class="tab-pane container" id="diskTab">
 
                    <div class="row user-list">
 
                        <div class="col-sm-3 user" style="">
 
                            <ul class="list-group" style="padding-top:100px">
 
                              <li class="list-group-item list-group-item-success">磁盘容量:<span class="badge" id="total"></span></li>
 
                              <li class="list-group-item list-group-item-info">已使用容量:<span class="badge" id="used"></span></li>
 
                              <li class="list-group-item list-group-item-warning">空闲容量:<span class="badge" id="free"></span></li>
 
                            </ul>
 
                        </div>
 
                        <div class="col-sm-9 user" style="">
 
                            <div id="disk" style="width:800px; height:300px;padding-top: 40px;margin-left: auto;margin-right: auto"></div>
 
                        </div>
 
                    </div>
 
 
 
                </div>
 
 
 
              </div>
 
 
 
            </div>
 
        </div>
 
      </div>
 
  </div>
 
</div>
 
 
 
    <script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
 
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
 
    <script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js"></script>
 
    <script>
 
        var chart = echarts.init(document.getElementById('cpu'), 'white', {renderer: 'canvas'});
 
        var memory = echarts.init(document.getElementById('memory'), 'white', {renderer: 'canvas'});
 
        var netio = echarts.init(document.getElementById('netio'), 'white', {renderer: 'canvas'});
 
        var disk = echarts.init(document.getElementById('disk'), 'white', {renderer: 'canvas'});
 
  
        $(
+
[[文件:python2022052701.png|600px]]
            function () {
 
                fetchData(chart);
 
                setInterval(fetchData, 2000);
 
                fetchMemoryData(memory);
 
                setInterval(fetchMemoryData, 2000);
 
                fetchNetioData(netio);
 
                setInterval(fetchNetioData, 2000);
 
                setInterval(fetchProcessData, 2000);
 
                fetchDiskData(disk);
 
                setInterval(fetchDiskData, 2000);
 
            },
 
            $('#myTabs a').click(function (e) {
 
              e.preventDefault()
 
              $(this).tab('show')
 
            })
 
        );
 
 
 
        function fetchData() {
 
            $.ajax({
 
                type: "GET",
 
                url: "http://127.0.0.1:5000/cpu",
 
                dataType: 'json',
 
                success: function (result) {
 
                    chart.setOption(result);
 
                }
 
            });
 
        }
 
 
 
        function fetchMemoryData() {
 
            $.ajax({
 
                type: "GET",
 
                url: "http://127.0.0.1:5000/memory",
 
                dataType: 'json',
 
                success: function (result) {
 
                    memory.setOption(JSON.parse(result.liquid));
 
                    $('#mtotal').html((result.mtotal/1024/1024/1024).toFixed(2) + 'G')
 
                    $('#mused').html((result.mused/1024/1024/1024).toFixed(2) + 'G')
 
                    $('#mfree').html((result.mfree/1024/1024/1024).toFixed(2) + 'G')
 
                    $('#stotal').html((result.stotal/1024/1024/1024).toFixed(2) + 'G')
 
                    $('#sused').html((result.sused/1024/1024/1024).toFixed(2) + 'G')
 
                    $('#sfree').html((result.sfree/1024/1024/1024).toFixed(2) + 'G')
 
                }
 
            });
 
        }
 
        function fetchNetioData() {
 
            $.ajax({
 
                type: "GET",
 
                url: "http://127.0.0.1:5000/netio",
 
                dataType: 'json',
 
                success: function (result) {
 
                    netio.setOption(result);
 
                }
 
            });
 
        }
 
        function fetchProcessData() {
 
            $.ajax({
 
                type: "GET",
 
                url: "http://127.0.0.1:5000/process",
 
                dataType: 'json',
 
                success: function (result) {
 
                    html = ''
 
                    list = result.list
 
                    for (var l in list) {
 
                        html = html +'<tr><td>' + list[l].PID + '</td><td>' + list[l].name + '</td><td>' + list[l].mem + '</td><td>' + list[l].ctime + '</td><td><button type="button" class="btn btn-default btn-xs" onclick="delProcess('+list[l].PID+')"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button></td></tr>'
 
                    }
 
                    $('#tbody').html(html)
 
                }
 
            })
 
        }
 
 
 
        function delProcess(pid) {
 
            $.ajax({
 
                type: "GET",
 
                url: "http://127.0.0.1:5000/delprocess?pid="+pid,
 
                dataType: 'json',
 
                success: function (result) {
 
                    $("#alert").fadeIn(1000);
 
                    $("#alert").fadeOut(3000);
 
                }
 
            })
 
        }
 
 
 
        function fetchDiskData() {
 
            $.ajax({
 
                type: "GET",
 
                url: "http://127.0.0.1:5000/disk",
 
                dataType: 'json',
 
                success: function (result) {
 
                    disk.setOption(JSON.parse(result.line));
 
                    $('#total').html((result.total/1000000000).toFixed(2) + 'G')
 
                    $('#used').html((result.used/1000000000).toFixed(2) + 'G')
 
                    $('#free').html((result.free/1000000000).toFixed(2) + 'G')
 
                }
 
            });
 
        }
 
 
 
    </script>
 
  </body>
 
</html></nowiki>
 
 
 
==效果==
 
[[文件:python22031901.png|600px]]
 
  
 
参考文档 : https://blog.csdn.net/ityouknow/article/details/105985451
 
参考文档 : https://blog.csdn.net/ityouknow/article/details/105985451

2022年5月28日 (六) 04:28的最新版本

简介

psutil 是一个跨平台库(http://pythonhosted.org/psutil)能够获取到系统运行的进程和系统利用率(包括CPU、内存、磁盘、网络等)信息。主要用来做系统监控,性能分析,进程管理。支持 Linux、Mac OS、Windows 系统。

本文以 psutil 模块获取系统信息开发一个监控 Windows /linux系统的平台。

技术选择

  • 监控的系统是 Windows /linux系统
  • 监控系统模块选择 psutil 模块
  • Web 框架选择的是 Flask 框架


技术准备

安装 Flask

Python:安装Flask

安装 psutil

windows/centos7:

pip3 install psutil

centos8:

Centos 8 配置yum源Centos 8安装psutil

获取系统信息

初始化

app.py:


import psutil
import os, signal
from random import randrange

from flask import Flask, render_template, jsonify, request
import time

app = Flask(__name__, static_folder="templates")

cpu_percent_dict = {}
net_io_dict = {'net_io_time':[], 'net_io_sent': [], 'net_io_recv': [], 'pre_sent': 0, 'pre_recv': 0, 'len': -1}
disk_dict = {'disk_time':[], 'write_bytes': [], 'read_bytes': [], 'pre_write_bytes': 0, 'pre_read_bytes': 0, 'len': -1}

cpu_percent_dict = {}

网页模板

templates/list.html:

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>基于psutil的系统监控工具</title>

    <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
  </head>


<body>
    <h1>{{title}}</h1>
     <table id="customers" class="table table-striped">
    <tr>
      <th>监测项</th>
      <th>数值</th>
    </tr>

    {% for key, value in my_dict.items() %}
    <tr>
      <td>{{ key }}</td>
      <td>{{ value}}</td>
    </tr>
    {% endfor %}
     </table>
</body>
</html>

CPU信息

通过 psutil 获取 CPU 信息

@app.route("/cpu")
def cpu():
    for i in range(1,6):
        # 当前时间
        now = time.strftime('%H:%M:%S', time.localtime(time.time()))
        #  CPU 负载
        cpu_percent = psutil.cpu_percent()
        cpu_percent_dict[now] = cpu_percent
        time.sleep(0.3)

    # 保持在图表中 10 个数据
    if len(cpu_percent_dict.keys()) == 11:
        cpu_percent_dict.pop(list(cpu_percent_dict.keys())[0])

    return render_template('list.html', title="CPU使用情况",my_dict=cpu_percent_dict)

if __name__ == '__main__':#程序入口
    #app.run()#让应用运行在本地服务器上。
    app.run(debug=True,host='0.0.0.0') #允许任意网址访问本站

Python2022052702.png

内存

@app.route("/memory")
def memory():
    memory = psutil.virtual_memory()
    swap = psutil.swap_memory()
    sys={}
    sys['mem_total']= memory.total
    sys['mem_used']= memory.used
    sys['mem_free']= memory.free
    sys['swap_total']=swap.total
    sys['swap_used']=swap.used
    sys['swap_free']=swap.free
    sys['memory_percent']= memory.percent

    return render_template('list.html', title="内存使用情况",my_dict=sys)




效果:

Python2022052701.png


https://blog.csdn.net/ityouknow/article/details/105985451

磁盘

通过 psutil 获取磁盘大小、分区、使用率和磁盘IO


网卡

通过 psutil 获取网络接口和网络连接的信息


代码

app.py

import psutil
import os, signal
from random import randrange

from flask import Flask, render_template, jsonify, request
import time

app = Flask(__name__, static_folder="templates")

cpu_percent_dict = {}
net_io_dict = {'net_io_time':[], 'net_io_sent': [], 'net_io_recv': [], 'pre_sent': 0, 'pre_recv': 0, 'len': -1}
disk_dict = {'disk_time':[], 'write_bytes': [], 'read_bytes': [], 'pre_write_bytes': 0, 'pre_read_bytes': 0, 'len': -1}

cpu_percent_dict = {}

@app.route("/cpu")
def cpu():
    for i in range(1,6):
        # 当前时间
        now = time.strftime('%H:%M:%S', time.localtime(time.time()))
        #  CPU 负载
        cpu_percent = psutil.cpu_percent()
        cpu_percent_dict[now] = cpu_percent
        time.sleep(0.3)

    # 保持在图表中 10 个数据
    if len(cpu_percent_dict.keys()) == 11:
        cpu_percent_dict.pop(list(cpu_percent_dict.keys())[0])

    return render_template('list.html', title="CPU使用情况",my_dict=cpu_percent_dict)

@app.route("/memory")
def memory():
    memory = psutil.virtual_memory()
    swap = psutil.swap_memory()
    sys={}
    sys['mem_total']= memory.total
    sys['mem_used']= memory.used
    sys['mem_free']= memory.free
    sys['swap_total']=swap.total
    sys['swap_used']=swap.used
    sys['swap_free']=swap.free
    sys['memory_percent']= memory.percent

    return render_template('list.html', title="内存使用情况",my_dict=sys)

if __name__ == '__main__':#程序入口
    #app.run()#让应用运行在本地服务器上。
    app.run(debug=True,host='0.0.0.0') #允许任意网址访问本站


templates/list.html

templates/list.html:

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>基于psutil的系统监控工具</title>

    <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
  </head>


<body>
    <h1>{{title}}</h1>
     <table id="customers" class="table table-striped">
    <tr>
      <th>监测项</th>
      <th>数值</th>
    </tr>

    {% for key, value in my_dict.items() %}
    <tr>
      <td>{{ key }}</td>
      <td>{{ value}}</td>
    </tr>
    {% endfor %}
     </table>
</body>

效果

Python2022052702.png

Python2022052701.png

参考文档 : https://blog.csdn.net/ityouknow/article/details/105985451