add(系统诊断: 设备检测和系统检测、dals中数据库路径)
This commit is contained in:
187
service/monitor_thread.py
Normal file
187
service/monitor_thread.py
Normal file
@ -0,0 +1,187 @@
|
||||
import configparser
|
||||
from typing import Dict, Union
|
||||
from icmplib import ping, ICMPLibError
|
||||
from PySide6.QtCore import QThread, Signal
|
||||
import socket
|
||||
|
||||
class MonitorThread(QThread):
|
||||
connect_success = Signal(str, int) # 成功信号:设备名称(str) + 延迟毫秒数(int)
|
||||
connect_failed = Signal(str) # 失败信号:设备名称(str)
|
||||
service_normal = Signal(str, int) # 服务正常信号: 服务名称(str) + 延迟毫秒数(int)
|
||||
service_error = Signal(str) # 服务异常信号:服务名称(str)
|
||||
state_result = Signal(str, int) # 全局状态(str: normal/warning/error) + 异常设备数量(int)
|
||||
check_finished = Signal() # 本轮检测结束
|
||||
|
||||
def __init__(self, config_path = "config/monitor_config.ini", parent=None):
|
||||
super().__init__(parent)
|
||||
# 初始化你的原有配置参数,完全不变
|
||||
self.config_path = config_path
|
||||
self.ping_timeout_ms = 1000
|
||||
self.ping_count = 2
|
||||
self.check_interval = 10 # 默认检测间隔10秒
|
||||
self.warning_delay = 30 # 默认的警告的网络延迟(单位: ms)
|
||||
self.is_stop = False # 线程停止标志位
|
||||
self.force_check = False # 立即检测标志
|
||||
|
||||
def _ping_device(self, ip: str, timeout_ms: int = 2000) -> Union[int, None]:
|
||||
"""设备连接状态检测"""
|
||||
try:
|
||||
response = ping(
|
||||
ip,
|
||||
count=self.ping_count,
|
||||
timeout=timeout_ms / 1000,
|
||||
privileged=False,
|
||||
interval=0.1
|
||||
)
|
||||
if response.is_alive:
|
||||
return int(response.avg_rtt)
|
||||
return None
|
||||
except ICMPLibError as e:
|
||||
print(f"IP[{ip}] ICMP异常: {str(e)}")
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"IP[{ip}] 未知异常: {str(e)}")
|
||||
return None
|
||||
|
||||
def _read_device_config(self) -> Dict[str, str]:
|
||||
"""读取ini配置文件"""
|
||||
device_dict = {} # 存储设备名和设备中的ip
|
||||
port_dict = {} # 存储服务名和服务的端口号
|
||||
config = configparser.ConfigParser()
|
||||
try:
|
||||
config.read(self.config_path, encoding="utf-8")
|
||||
for section in config.sections():
|
||||
if "ip" in config[section]:
|
||||
device_ip = config[section]["ip"].strip()
|
||||
device_dict[section] = device_ip
|
||||
if "port" in config[section]:
|
||||
service_port = config[section]["port"].strip()
|
||||
port_dict[section] = int(service_port)
|
||||
except ValueError:
|
||||
print(f"配置文件[{self.config_path}]: [{section}] 下的端口值[{service_port}]格式错误")
|
||||
except FileNotFoundError:
|
||||
print(f"配置文件[{self.config_path}]不存在,请检查路径!")
|
||||
except Exception as e:
|
||||
print(f"读取配置文件失败: {str(e)}")
|
||||
return device_dict, port_dict
|
||||
|
||||
def check_service_status(self, ip: str, port: int, timeout: float = 1.0) -> bool:
|
||||
"""
|
||||
检测指定IP的指定端口的服务是否正常
|
||||
:param ip: 目标IP地址
|
||||
:param port: 目标端口号
|
||||
:param timeout: 超时时间
|
||||
:return: True=服务正常, False=服务异常
|
||||
"""
|
||||
try:
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.settimeout(timeout)
|
||||
result = sock.connect_ex((ip, port)) # 0=连接成功,其他=失败
|
||||
sock.close()
|
||||
return result == 0
|
||||
except Exception as e:
|
||||
return False
|
||||
|
||||
def run(self) -> None:
|
||||
"""网络设备检测"""
|
||||
print("设备/服务检测线程已启动")
|
||||
self.is_stop = False # 重置停止标志位
|
||||
while True:
|
||||
# 线程退出
|
||||
if self.is_stop:
|
||||
break
|
||||
|
||||
# 批量检测所有设备
|
||||
device_dict, port_dict = self._read_device_config()
|
||||
check_result = {} # 所有的检测结果
|
||||
if not device_dict:
|
||||
print("设备/服务检测线程: 未读取到任何配置或配置异常!")
|
||||
else:
|
||||
for device_name, device_ip in device_dict.items():
|
||||
if self.is_stop:
|
||||
break
|
||||
delay_ms = self._ping_device(device_ip, self.ping_timeout_ms)
|
||||
if device_name not in port_dict: # 只是设备而不是服务
|
||||
if delay_ms is not None:
|
||||
self.connect_success.emit(device_name, delay_ms) # 发送成功信号
|
||||
else:
|
||||
self.connect_failed.emit(device_name) # 发送失败信号
|
||||
else: # 服务
|
||||
service_name = device_name # 此时,设备名就是服务名
|
||||
if delay_ms is None:
|
||||
self.service_error.emit(service_name)
|
||||
else:
|
||||
status = self.check_service_status(device_ip, port_dict[device_name])
|
||||
if status: # 服务正常
|
||||
self.service_normal.emit(service_name, delay_ms)
|
||||
else: # 服务异常
|
||||
self.service_error.emit(service_name)
|
||||
delay_ms = None # 标志服务异常
|
||||
|
||||
check_result[device_name] = delay_ms
|
||||
|
||||
# 本轮检测完成
|
||||
self.check_finished.emit()
|
||||
|
||||
# 状态统计
|
||||
self._calc_state(check_result)
|
||||
|
||||
|
||||
# 等待指定间隔后,继续下一次检测
|
||||
# self.msleep(self.check_interval * 1000)
|
||||
sleep_total_ms = self.check_interval * 1000
|
||||
sleep_slice_ms = 200 # 每次休眠200ms
|
||||
sleep_count = int(sleep_total_ms / sleep_slice_ms)
|
||||
for _ in range(sleep_count):
|
||||
if self.is_stop: # 每次休眠后检测退出标志
|
||||
break
|
||||
if self.force_check:
|
||||
self.force_check = False
|
||||
break
|
||||
self.msleep(sleep_slice_ms)
|
||||
|
||||
# ============ 状态统计 ============
|
||||
def _calc_state(self, check_result:dict):
|
||||
offline_count = 0 # 离线(异常)数
|
||||
delay_warn_count = 0# 延迟超30ms的设备/服务数
|
||||
# 遍历结果统计
|
||||
for delay in check_result.values():
|
||||
if delay is None:
|
||||
offline_count += 1
|
||||
elif delay >= self.warning_delay:
|
||||
delay_warn_count += 1
|
||||
# 按优先级判定全局状态
|
||||
if offline_count > 0:
|
||||
# 设备/服务异常 → error + 离线(异常)数量
|
||||
self.state_result.emit("error", offline_count)
|
||||
elif delay_warn_count > 0:
|
||||
# 全部正常但有延迟超标 → warning + 延迟超标数量
|
||||
self.state_result.emit("warning", delay_warn_count)
|
||||
else:
|
||||
# 全部正常且延迟都<30ms → normal + 0
|
||||
self.state_result.emit("normal", 0)
|
||||
|
||||
# ============ 修改检测间隔 ============
|
||||
def set_check_interval(self, interval: int):
|
||||
"""
|
||||
修改检测时间间隔
|
||||
:param interval: 间隔秒数(int)
|
||||
"""
|
||||
if isinstance(interval, int) and interval >= 3:
|
||||
self.check_interval = interval
|
||||
|
||||
# ============ 修改警告延迟 ============
|
||||
def set_warning_delay(self, delay:int):
|
||||
if isinstance(delay, int) and delay >= 1:
|
||||
self.warning_delay = delay
|
||||
|
||||
# ============ 停止检测线程============
|
||||
def stop_thread(self):
|
||||
self.is_stop = True
|
||||
self.wait()
|
||||
print("设备/服务检测线程已退出")
|
||||
|
||||
# ============ 立即检测============
|
||||
def force_immediate_check(self):
|
||||
"""马上执行新一轮检测"""
|
||||
self.force_check = True
|
||||
Reference in New Issue
Block a user