Update: (步骤备份)完善系统监控

This commit is contained in:
wojiaoyishang
2025-01-21 20:58:37 +08:00
parent 3bb59d3786
commit de36a9936a
10 changed files with 583 additions and 167 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ from io import BytesIO
from flask import session, make_response
from applications.common.utils.gen_captcha import vieCode
from applications.common.utils.captcha import vieCode
# 生成验证码
+56
View File
@@ -0,0 +1,56 @@
import time
cache_dict = {}
def cache_set_internal(key, value, expired=5):
"""
程序内部实现的记录缓存,用于简单、体量不大的缓存记录,在程序结束后销毁。对于高速、体量大的环境请配置 Redis 等服务自行记录。
记录缓存,存储键值对,并记录当前时间作为缓存的时间戳。
:param key: 键
:param value: 值
:param expired: 过期时间(秒),默认5秒
"""
cache_dict[key] = {
'value': value,
'expired_time': time.time() + expired
}
def cache_get_internal(key):
"""
获取缓存,根据键从缓存中获取值,并检查是否过期。
:param key: 键
:return: 如果缓存存在且未过期,返回缓存的值;否则返回 None
"""
if key in cache_dict:
cache_item = cache_dict[key]
if time.time() < cache_item['expired_time']:
return cache_item['value']
else:
# 如果缓存已过期,删除该缓存
del cache_dict[key]
return None
def cache_auto_internal(key, call, expired=5):
"""
如果缓存存在直接返回缓存内容,缓存不存在或者过期执行 call 函数,并取得返回值记录并返回。
:param key: 键
:param call: 获取新值的地方
:param expired: 过期时间(秒),默认5秒
"""
data = cache_get_internal(key)
if data is not None:
return data
data = call()
cache_set_internal(key, data, expired)
return data
@@ -14,7 +14,7 @@ class vieCode:
__inCurve = True # 是否画干扰线
__inNoise = True # 是否画干扰点
__type = 2 # 验证码类型 1、纯字母 2、数字字母混合
__fontPatn = 'applications/common/utils/fonts/1.ttf' # 字体
__fontPatn = 'applications/common/utils/fonts/captcha.ttf' # 字体
def GetCodeImage(self, size=80, length=4):
'''获取验证码图片
+26 -26
View File
@@ -11,7 +11,7 @@ def str_escape(s):
between = validators.between
'''
"""
验证数字是否介于最小值和/或最大值之间。
这将适用于任何类似的类型,如浮点数、小数和日期,而不仅仅是整数。
between(value, min=None, max=None)
@@ -35,10 +35,10 @@ between(value, min=None, max=None)
... min=datetime(1999, 11, 11)
... )
True
'''
"""
domain = validators.domain
'''
"""
返回给定值是否为有效域
如果值是有效域名,则此函数返回 True ,否则返回 ValidationFailure
domain(value)
@@ -49,10 +49,10 @@ domain(value)
>>> domain('example.com/')
ValidationFailure(func=domain, ...)
'''
"""
email = validators.email
'''
"""
验证电子邮件地址。验证成功时返回 True ,验证失败时返回
>>> email('someone@example.com')
@@ -60,10 +60,10 @@ email = validators.email
>>> email('bogus@@')
ValidationFailure(func=email, ...)
'''
"""
iban = validators.iban
'''
"""
返回给定值是否为有效的IBAN代码。
如果值是有效的IBAN,则此函数返回 True ,否则返回 ValidationFailure 。
@@ -72,10 +72,10 @@ iban = validators.iban
>>> iban('123456')
ValidationFailure(func=iban, ...)
'''
"""
ipv4 = validators.ipv4
'''
"""
返回给定值是否为有效的IPv4地址。
>>> ipv4('123.0.0.7')
@@ -83,20 +83,20 @@ ipv4 = validators.ipv4
>>> ipv4('900.80.70.11')
ValidationFailure(func=ipv4, args={'value': '900.80.70.11'})
'''
"""
ipv6 = validators.ipv6
'''
"""
返回给定值是否为有效的IP版本6地址。
>>> ipv6('abcd:ef::42:1')
True
>>> ipv6('abc.0.0.1')
ValidationFailure(func=ipv6, args={'value': 'abc.0.0.1'})
'''
"""
length = validators.length
'''
"""
返回给定字符串的长度是否在指定范围内。
>>> length('something', min=2)
True
@@ -106,10 +106,10 @@ length = validators.length
>>> length('something', max=5)
ValidationFailure(func=length, ...)
'''
"""
mac_address = validators.mac_address
'''
"""
返回给定值是否为有效MAC地址。
如果该值是有效的MAC地址,则此函数返回 True ,否则返回 ValidationFailure 。
@@ -118,10 +118,10 @@ mac_address = validators.mac_address
>>> mac_address('00:00:00:00:00')
ValidationFailure(func=mac_address, args={'value': '00:00:00:00:00'})
'''
"""
slug = validators.slug
'''
"""
验证给定值是否为有效的块。
有效的短信息只能包含字母数字字符、连字符和下划线。
>>> slug('my.slug')
@@ -129,15 +129,15 @@ slug = validators.slug
>>> slug('my-slug-2134')
True
'''
"""
#truthy = validators.truthy
'''
"""
验证给定值不是错误值。
'''
"""
url = validators.url
'''
"""
返回给定值是否为有效URL。
如果值是有效URL,则此函数返回 True ,否则返回 ValidationFailure 。
@@ -152,10 +152,10 @@ url = validators.url
>>> url('http://10.0.0.1', public=True)
ValidationFailure(func=url, ...)
'''
"""
uuid = validators.uuid
'''
"""
返回给定值是否为有效UUID。
如果值是有效的UUID,则此函数返回 True ,否则返回 ValidationFailure 。
@@ -164,7 +164,7 @@ uuid = validators.uuid
>>> uuid('2bc1c94f 0deb-43e9-92a1-4775189ec9f8')
ValidationFailure(func=uuid, ...)
'''
"""
@validator
@@ -172,7 +172,7 @@ def even(value):
return not (value % 2)
'''
"""
一个装饰器,它使给定的函数验证器
每当给定函数被调用并返回 False 值时,这个装饰器返回 ValidationFailure 对象。
>>> @validator
@@ -184,4 +184,4 @@ True
>>> even(5)
ValidationFailure(func=even, args={'value': 5})
'''
"""
+116 -47
View File
@@ -1,47 +1,33 @@
import os
import platform
import re
import sys
import time
import psutil
import platform
from datetime import datetime
import psutil
from flask import Blueprint, render_template, jsonify
from flask import Blueprint, render_template
from applications.common.utils.http import table_api, success_api
from applications.common.utils.rights import authorize
from applications.common.utils.cache import cache_auto_internal
bp = Blueprint('adminMonitor', __name__, url_prefix='/monitor')
# 系统监控
@bp.get('/')
@authorize("system:monitor:main")
def main():
# 主机名称
hostname = platform.node()
# 系统版本
system_version = platform.platform()
# python版本
python_version = platform.python_version()
# 逻辑cpu数量
cpu_count = psutil.cpu_count()
# cpu使用率
cpus_percent = psutil.cpu_percent(interval=0.1, percpu=False) # percpu 获取主使用率
# 内存
memory_information = psutil.virtual_memory()
# 内存使用率
memory_usage = memory_information.percent
memory_used: int = memory_information.used
memory_total: int = memory_information.total
memory_free: int = memory_information.free
# 磁盘信息
def get_disk_partitions_list():
disk_partitions_list = []
# 判断是否在容器中
if not os.path.exists('/.dockerenv'):
disk_partitions = psutil.disk_partitions()
for i in disk_partitions:
a = psutil.disk_usage(i.device)
try:
a = psutil.disk_usage(i.device)
except PermissionError:
continue
disk_partitions_dict = {
'device': i.device,
'fstype': i.fstype,
@@ -51,30 +37,58 @@ def main():
'percent': a.percent
}
disk_partitions_list.append(disk_partitions_dict)
else:
try:
usage = psutil.disk_usage('/')
except PermissionError:
pass
disk_partitions_list.append({
'device': '/', # 设备名称(根文件系统)
'fstype': psutil.disk_partitions()[0].fstype, # 文件系统类型
'total': usage.total, # 总容量(字节)
'used': usage.used, # 已用空间(字节)
'free': usage.free, # 可用空间(字节)
'percent': usage.percent # 使用百分比
})
return disk_partitions_list
def get_basic_info():
# 主机名称
hostname = platform.node()
# 系统版本
system_version = platform.platform()
# Python 版本
python_version = platform.python_version()
# 开机时间
boot_time = datetime.fromtimestamp(psutil.boot_time()).replace(microsecond=0)
up_time = datetime.now().replace(microsecond=0) - boot_time
up_time_list = re.split(r':', str(up_time))
up_time_format = " {} 小时{} 分钟{}".format(up_time_list[0], up_time_list[1], up_time_list[2])
up_time_format = "{} 小时 {} 分钟 {}".format(up_time_list[0], up_time_list[1], up_time_list[2])
up_time_format = up_time_format.replace("days,", "")
return {
'hostname': hostname,
'system_version': system_version,
'python_version': python_version,
'boot_time': boot_time,
'up_time_format': up_time_format
}
# 系统监控
@bp.get('/')
@authorize("system:monitor:main")
def main():
# 当前时间
time_now = time.strftime('%H:%M:%S ', time.localtime(time.time()))
return render_template(
'system/monitor.html',
hostname=hostname,
system_version=system_version,
python_version=python_version,
cpus_percent=cpus_percent,
memory_usage=memory_usage,
cpu_count=cpu_count,
memory_used=memory_used,
memory_total=memory_total,
memory_free=memory_free,
boot_time=boot_time,
up_time_format=up_time_format,
disk_partitions_list=disk_partitions_list,
time_now=time_now
time_now=time_now,
**get_basic_info()
)
@@ -82,19 +96,74 @@ def main():
@bp.get('/polling')
@authorize("system:monitor:main")
def ajax_polling():
# 获取cpu使用率
cpus_percent = psutil.cpu_percent(interval=0.1, percpu=False) # percpu 获取主使用率
# 获取内存使用率
memory_information = psutil.virtual_memory()
# 获取 CPU 核心数
cpu_count = cache_auto_internal('cpu_count', lambda: psutil.cpu_count(), expired=999999999)
# 获取 CPU 使用率
cpus_percent = cache_auto_internal('cpus_percent',
lambda: psutil.cpu_percent(interval=1, percpu=False),
expired=5)
# 每个 CPU 的使用率
cpu_percent_per_core = cache_auto_internal('cpu_percent_per_core',
lambda: list(enumerate(psutil.cpu_percent(interval=1, percpu=True))),
expired=5)
# 获取空闲率、等待率
cpu_times_percent = cache_auto_internal('cpu_times_percent',
lambda: psutil.cpu_times_percent(interval=1, percpu=False),
expired=5)
# 内存信息
memory_information = cache_auto_internal('memory_information',
psutil.virtual_memory,
expired=5)
# 硬盘信息
disk_partitions_list = cache_auto_internal('disk_partitions_list',
get_disk_partitions_list,
expired=5)
# 系统信息
basic_info = cache_auto_internal('basic_info',
get_basic_info,
expired=5)
memory_usage = memory_information.percent
time_now = time.strftime('%H:%M:%S ', time.localtime(time.time()))
return jsonify(cups_percent=cpus_percent, memory_used=memory_usage, time_now=time_now)
memory_used = memory_information.used
memory_total = memory_information.total
memory_free = memory_information.free
cpu_idle_percent = cpu_times_percent.idle
if hasattr(cpu_times_percent, 'iowait'):
cpu_wait_percent = cpu_times_percent.iowait
else:
cpu_wait_percent = "-"
return table_api(msg="请求成功",
count=0,
data={
'cpu_count': cpu_count,
'cpus_percent': cpus_percent,
'cpu_idle_percent': cpu_idle_percent,
'cpu_wait_percent': cpu_wait_percent,
'cpu_percent_per_core': cpu_percent_per_core,
'memory_used': memory_used,
'memory_total': memory_total,
'memory_free': memory_free,
'memory_usage': memory_usage,
'disk_partitions_list': disk_partitions_list,
'time_now': time.strftime('%H:%M:%S', time.localtime(time.time())),
'basic_info': basic_info
})
# 关闭程序
@bp.get('/kill')
@authorize("system:monitor:main")
def kill():
# 注:若是多 worker 则不生效
return success_api(msg="关闭命令已发送,请修改代码以生效。")
for proc in psutil.process_iter():
if proc.pid == os.getpid():
proc.kill()