- 新增 aio-mcp 项目框架 - 新增 .trae/skills/ OCR/SKU 设计工具 - 更新 auto-check 配置和 stress 包 - 删除 fnhelp 文档目录 - 更新 Docker 压力测试脚本
757 lines
27 KiB
Python
757 lines
27 KiB
Python
#!/usr/bin/env python
|
||
import os
|
||
import subprocess
|
||
import psutil
|
||
import time
|
||
import signal
|
||
import sys
|
||
import argparse
|
||
|
||
# 尝试导入textual库,如果不存在则设置标志
|
||
HAS_TEXTUAL = True
|
||
try:
|
||
from textual.app import App, ComposeResult
|
||
from textual.widgets import Header, Footer, Static, Button, Label, Input
|
||
from textual.containers import Container, Horizontal, Vertical
|
||
from textual.screen import Screen, ModalScreen
|
||
import asyncio
|
||
except ImportError:
|
||
HAS_TEXTUAL = False
|
||
# 如果没有textual但尝试无参数运行,我们需要提示用户
|
||
if len(sys.argv) == 1:
|
||
print("错误: 未安装textual库,无法启动图形界面。")
|
||
print("您可以通过命令行参数使用此脚本的核心功能:")
|
||
print(" 内存测试: python self_inspection.py --memory")
|
||
print(" CPU测试: python self_inspection.py --cpu [测试时长(秒)]")
|
||
print(" 查看帮助: python self_inspection.py -h")
|
||
sys.exit(1)
|
||
|
||
# 定义颜色常量(保留以兼容原始代码)
|
||
RESET = "\033[0m"
|
||
BOLD = "\033[1m"
|
||
RED = "\033[31m"
|
||
GREEN = "\033[32m"
|
||
YELLOW = "\033[33m"
|
||
BLUE = "\033[34m"
|
||
MAGENTA = "\033[35m"
|
||
CYAN = "\033[36m"
|
||
WHITE = "\033[37m"
|
||
|
||
# 全局变量存储当前运行的进程
|
||
current_process = None
|
||
|
||
# 工具函数
|
||
def clear_screen():
|
||
"""清空终端屏幕"""
|
||
os.system('clear' if os.name == 'posix' else 'cls')
|
||
|
||
def get_test_memory():
|
||
"""计算可用于测试的内存 (剩余内存的 97%)"""
|
||
available_memory = psutil.virtual_memory().available // (1024 * 1024) # 获取可用内存 (MB)
|
||
return int(available_memory * 0.97) # 取 97% 进行测试
|
||
|
||
def check_memory_usage():
|
||
"""检查当前内存使用情况"""
|
||
return psutil.virtual_memory().percent
|
||
|
||
def run_command(command):
|
||
"""执行命令并返回结果"""
|
||
global current_process
|
||
|
||
result = {
|
||
'status_code': 0,
|
||
'stdout': '',
|
||
'stderr': ''
|
||
}
|
||
|
||
try:
|
||
# 保存进程引用以便后续可以终止
|
||
current_process = subprocess.Popen(
|
||
command,
|
||
stdout=subprocess.PIPE,
|
||
stderr=subprocess.PIPE,
|
||
text=True,
|
||
bufsize=1
|
||
)
|
||
|
||
# 等待进程完成
|
||
stdout, stderr = current_process.communicate()
|
||
|
||
# 获取返回码
|
||
result['status_code'] = current_process.returncode
|
||
result['stdout'] = stdout
|
||
result['stderr'] = stderr
|
||
|
||
# 清除当前进程引用
|
||
current_process = None
|
||
|
||
return result
|
||
except Exception as e:
|
||
if current_process:
|
||
try:
|
||
current_process.terminate()
|
||
except:
|
||
pass
|
||
current_process = None
|
||
|
||
result['status_code'] = 1
|
||
result['stderr'] = str(e)
|
||
return result
|
||
|
||
def stop_current_process():
|
||
"""停止当前正在运行的进程"""
|
||
global current_process
|
||
if current_process:
|
||
try:
|
||
current_process.terminate()
|
||
# 给进程一点时间来终止
|
||
time.sleep(0.5)
|
||
# 如果进程还在运行,强制结束
|
||
if current_process.poll() is None:
|
||
current_process.kill()
|
||
return True
|
||
except Exception:
|
||
return False
|
||
finally:
|
||
current_process = None
|
||
return False
|
||
|
||
# 命令行直接执行内存测试的函数
|
||
def cli_memory_test():
|
||
"""通过命令行直接执行内存测试"""
|
||
memory_usage = check_memory_usage()
|
||
|
||
if memory_usage > 80:
|
||
print(f"警告: 当前系统内存使用率已达 {memory_usage}%!")
|
||
print("建议关闭一些软件后再运行,继续运行可能检测效果不够准确")
|
||
print("是否继续? (y/n)")
|
||
response = input().strip().lower()
|
||
if response != 'y':
|
||
print("操作已取消")
|
||
return False
|
||
|
||
print("建议关闭所有docker容器以及停用所有应用程序以保证检测的准确性。")
|
||
print("是否继续? (y/n)")
|
||
response = input().strip().lower()
|
||
if response != 'y':
|
||
print("操作已取消")
|
||
return False
|
||
|
||
mem_size = f"{get_test_memory()}M"
|
||
print("正在运行内存测试,请勿进行其它操作,如果运行过程中出现死机重启则大概率为内存问题。")
|
||
print("整个测试过程预计 30-120 分钟 具体根据内存大小,如果需要终止测试请按Ctrl+C。")
|
||
|
||
try:
|
||
# 设置信号处理器以便可以通过Ctrl+C终止测试
|
||
def signal_handler(sig, frame):
|
||
print("\n测试已被用户终止")
|
||
stop_current_process()
|
||
sys.exit(0)
|
||
|
||
signal.signal(signal.SIGINT, signal_handler)
|
||
|
||
# 执行测试
|
||
result = run_command(["sudo", "memtester", mem_size, "1"])
|
||
|
||
if result['status_code'] == 0:
|
||
print("内存测试完成!未发现问题。")
|
||
return True
|
||
else:
|
||
print(f"内存测试失败!错误信息:{result['stderr']}")
|
||
return False
|
||
|
||
except Exception as e:
|
||
print(f"测试过程中发生错误: {str(e)}")
|
||
return False
|
||
|
||
# 命令行直接执行CPU测试的函数
|
||
def cli_cpu_test(duration=60):
|
||
"""通过命令行直接执行CPU测试
|
||
|
||
Args:
|
||
duration (int): 测试持续时间(秒),默认为60秒
|
||
"""
|
||
try:
|
||
duration = int(duration)
|
||
if duration <= 0:
|
||
print("错误: 测试时长必须大于0")
|
||
return False
|
||
except ValueError:
|
||
print("错误: 测试时长必须是一个有效的整数")
|
||
return False
|
||
|
||
print(f"正在进行 CPU 压测,持续 {duration} 秒...如需提前结束测试,请按Ctrl+C。")
|
||
|
||
try:
|
||
# 设置信号处理器以便可以通过Ctrl+C终止测试
|
||
def signal_handler(sig, frame):
|
||
print("\n测试已被用户终止")
|
||
stop_current_process()
|
||
sys.exit(0)
|
||
|
||
signal.signal(signal.SIGINT, signal_handler)
|
||
|
||
# 执行测试
|
||
result = run_command(["stress", "--cpu", "4", "--timeout", str(duration)])
|
||
|
||
if result['status_code'] == 0:
|
||
print("CPU 压测完成!未发现问题。")
|
||
return True
|
||
else:
|
||
print(f"CPU 压测失败!错误信息:{result['stderr']}")
|
||
return False
|
||
|
||
except Exception as e:
|
||
print(f"测试过程中发生错误: {str(e)}")
|
||
return False
|
||
|
||
def parse_arguments():
|
||
"""解析命令行参数"""
|
||
parser = argparse.ArgumentParser(description='系统健康检测工具')
|
||
parser.add_argument('--memory', action='store_true',
|
||
help='执行内存测试')
|
||
parser.add_argument('--cpu', nargs='?', const=60, type=int,
|
||
help='执行CPU压测,可选参数为测试时长(秒),默认为60秒')
|
||
return parser.parse_args()
|
||
|
||
# 只有在导入了textual库的情况下才定义这些类
|
||
if HAS_TEXTUAL:
|
||
# 确认对话框
|
||
class ConfirmDialog(ModalScreen):
|
||
"""确认对话框"""
|
||
|
||
def __init__(self, message: str, action_callback=None):
|
||
super().__init__()
|
||
self.message = message
|
||
self.action_callback = action_callback
|
||
|
||
def compose(self) -> ComposeResult:
|
||
with Container(id="dialog-container"):
|
||
yield Label(f"[yellow]{self.message}[/yellow]", id="dialog-title")
|
||
with Horizontal(id="dialog-buttons"):
|
||
yield Button("确认", id="confirm", variant="primary")
|
||
yield Button("取消", id="cancel", variant="error")
|
||
|
||
def on_button_pressed(self, event: Button.Pressed) -> None:
|
||
if event.button.id == "confirm" and self.action_callback:
|
||
self.dismiss(True)
|
||
self.action_callback()
|
||
else:
|
||
self.dismiss(False)
|
||
|
||
# 成功提示对话框
|
||
class SuccessDialog(ModalScreen):
|
||
"""成功提示对话框"""
|
||
|
||
def __init__(self, message: str):
|
||
super().__init__()
|
||
self.message = message
|
||
|
||
def compose(self) -> ComposeResult:
|
||
with Container(id="dialog-container"):
|
||
yield Label(f"[green]{self.message}[/green]", id="dialog-title")
|
||
with Horizontal(id="dialog-buttons"):
|
||
yield Button("确定", id="ok", variant="primary")
|
||
|
||
def on_button_pressed(self, event: Button.Pressed) -> None:
|
||
self.dismiss(True)
|
||
|
||
# 错误提示对话框
|
||
class ErrorDialog(ModalScreen):
|
||
"""错误提示对话框"""
|
||
|
||
def __init__(self, message: str):
|
||
super().__init__()
|
||
self.message = message
|
||
|
||
def compose(self) -> ComposeResult:
|
||
with Container(id="dialog-container"):
|
||
yield Label(f"[red]{self.message}[/red]", id="dialog-title")
|
||
with Horizontal(id="dialog-buttons"):
|
||
yield Button("确定", id="ok", variant="primary")
|
||
|
||
def on_button_pressed(self, event: Button.Pressed) -> None:
|
||
self.dismiss(True)
|
||
|
||
# 输入对话框
|
||
class InputDialog(ModalScreen):
|
||
"""输入对话框"""
|
||
|
||
def __init__(self, message: str, default_value: str = "", action_callback=None):
|
||
super().__init__()
|
||
self.message = message
|
||
self.default_value = default_value
|
||
self.action_callback = action_callback
|
||
|
||
def compose(self) -> ComposeResult:
|
||
with Container(id="dialog-container"):
|
||
yield Label(f"[blue]{self.message}[/blue]", id="dialog-title")
|
||
yield Input(value=self.default_value, id="input-field")
|
||
with Horizontal(id="dialog-buttons"):
|
||
yield Button("确认", id="confirm", variant="primary")
|
||
yield Button("取消", id="cancel", variant="error")
|
||
|
||
def on_button_pressed(self, event: Button.Pressed) -> None:
|
||
if event.button.id == "confirm" and self.action_callback:
|
||
input_value = self.query_one("#input-field", Input).value
|
||
self.dismiss(input_value)
|
||
self.action_callback(input_value)
|
||
else:
|
||
self.dismiss(None)
|
||
|
||
class SystemHealthApp(App):
|
||
CSS = """
|
||
Screen {
|
||
background: $surface;
|
||
}
|
||
|
||
#title {
|
||
dock: top;
|
||
text-align: center;
|
||
text-style: bold;
|
||
background: $accent;
|
||
color: $text;
|
||
padding: 1;
|
||
margin-bottom: 1;
|
||
}
|
||
|
||
#main-container {
|
||
width: 100%;
|
||
height: auto;
|
||
padding: 1;
|
||
}
|
||
|
||
#menu-container {
|
||
width: 100%;
|
||
height: auto;
|
||
margin: 1;
|
||
border: solid $primary;
|
||
padding: 1;
|
||
}
|
||
|
||
.menu-button {
|
||
margin: 1;
|
||
min-width: 30;
|
||
min-height: 3;
|
||
background: $primary;
|
||
color: $text;
|
||
border: tall $primary-lighten-2;
|
||
}
|
||
|
||
#memory-test {
|
||
background: $success-darken-1;
|
||
color: $text;
|
||
border: tall $success;
|
||
}
|
||
|
||
#cpu-test {
|
||
background: $warning-darken-1;
|
||
color: $text;
|
||
border: tall $warning;
|
||
}
|
||
|
||
#stop-test {
|
||
background: $error-darken-1;
|
||
color: $text;
|
||
border: tall $error;
|
||
margin: 1;
|
||
min-width: 30;
|
||
min-height: 3;
|
||
}
|
||
|
||
#status {
|
||
height: auto;
|
||
min-height: 3;
|
||
margin: 1;
|
||
padding: 1;
|
||
border: solid $accent;
|
||
background: $surface-darken-1;
|
||
}
|
||
|
||
/* 对话框样式 */
|
||
#dialog-container {
|
||
width: 60%;
|
||
height: auto;
|
||
padding: 2;
|
||
background: $surface;
|
||
border: thick $accent;
|
||
margin: 1 0;
|
||
}
|
||
|
||
/* 成功对话框样式 */
|
||
SuccessDialog #dialog-container {
|
||
border: thick $success;
|
||
}
|
||
|
||
/* 错误对话框样式 */
|
||
ErrorDialog #dialog-container {
|
||
border: thick $error;
|
||
}
|
||
|
||
/* 确认对话框样式 */
|
||
ConfirmDialog #dialog-container {
|
||
border: thick $warning;
|
||
}
|
||
|
||
/* 输入对话框样式 */
|
||
InputDialog #dialog-container {
|
||
border: thick $primary;
|
||
}
|
||
|
||
#dialog-title {
|
||
text-align: center;
|
||
width: 100%;
|
||
margin-bottom: 2;
|
||
}
|
||
|
||
#input-field {
|
||
margin-bottom: 1;
|
||
}
|
||
|
||
#dialog-buttons {
|
||
align: center middle;
|
||
width: 100%;
|
||
}
|
||
|
||
#dialog-buttons Button {
|
||
margin: 0 2;
|
||
min-width: 10;
|
||
}
|
||
|
||
/* 按钮样式增强 */
|
||
Button {
|
||
background: $primary;
|
||
border: tall $primary-lighten-2;
|
||
padding: 1 2;
|
||
}
|
||
|
||
Button:hover {
|
||
background: $primary-lighten-1;
|
||
}
|
||
|
||
Button#confirm {
|
||
background: $success-darken-1;
|
||
border: tall $success;
|
||
}
|
||
|
||
Button#confirm:hover {
|
||
background: $success;
|
||
}
|
||
|
||
Button#cancel, Button#stop-test {
|
||
background: $error-darken-1;
|
||
border: tall $error;
|
||
}
|
||
|
||
Button#cancel:hover, Button#stop-test:hover {
|
||
background: $error;
|
||
}
|
||
|
||
Button#ok {
|
||
background: $primary-darken-1;
|
||
border: tall $primary;
|
||
}
|
||
|
||
Button#ok:hover {
|
||
background: $primary;
|
||
}
|
||
"""
|
||
|
||
BINDINGS = [
|
||
("q", "quit", "退出"),
|
||
("escape", "quit", "退出"),
|
||
("ctrl+c", "stop_test", "停止测试"),
|
||
]
|
||
|
||
def __init__(self):
|
||
super().__init__()
|
||
self.is_testing = False
|
||
|
||
def compose(self) -> ComposeResult:
|
||
yield Header(show_clock=True)
|
||
yield Footer()
|
||
|
||
with Container(id="main-container"):
|
||
yield Label("[b]系统健康检测工具[/b]", id="title")
|
||
|
||
with Container(id="menu-container"):
|
||
yield Button("内存检测 (使用 memtester)", id="memory-test", classes="menu-button")
|
||
yield Button("CPU 压测", id="cpu-test", classes="menu-button")
|
||
yield Button("停止当前测试", id="stop-test", disabled=True)
|
||
|
||
# 状态输出
|
||
yield Static("准备就绪,请选择检测项目。", id="status")
|
||
|
||
def on_button_pressed(self, event: Button.Pressed) -> None:
|
||
"""按钮点击事件处理"""
|
||
button_id = event.button.id
|
||
|
||
if button_id == "memory-test":
|
||
self.start_memory_test()
|
||
elif button_id == "cpu-test":
|
||
self.start_cpu_test()
|
||
elif button_id == "stop-test":
|
||
self.stop_test()
|
||
|
||
def action_stop_test(self) -> None:
|
||
"""键盘快捷键停止测试"""
|
||
self.stop_test()
|
||
|
||
def stop_test(self) -> None:
|
||
"""停止当前测试"""
|
||
if not self.is_testing:
|
||
return
|
||
|
||
status = self.query_one("#status")
|
||
status.update("[yellow]正在停止测试...[/yellow]")
|
||
|
||
# 停止当前进程
|
||
if stop_current_process():
|
||
status.update("[green]测试已停止。[/green]")
|
||
self.show_success_dialog("测试已成功停止。")
|
||
else:
|
||
status.update("[red]无法停止测试,可能测试已经完成。[/red]")
|
||
|
||
# 更新界面状态
|
||
self.is_testing = False
|
||
|
||
# 使用try/except捕获可能的NoMatches异常
|
||
try:
|
||
stop_button = self.query_one("#stop-test", Button)
|
||
if stop_button:
|
||
stop_button.disabled = True
|
||
|
||
memory_button = self.query_one("#memory-test", Button)
|
||
if memory_button:
|
||
memory_button.disabled = False
|
||
|
||
cpu_button = self.query_one("#cpu-test", Button)
|
||
if cpu_button:
|
||
cpu_button.disabled = False
|
||
except Exception as e:
|
||
# 记录错误但不中断程序
|
||
print(f"更新按钮状态时出错: {str(e)}")
|
||
|
||
def start_memory_test(self) -> None:
|
||
"""开始内存测试"""
|
||
status = self.query_one("#status")
|
||
memory_usage = check_memory_usage()
|
||
|
||
if memory_usage > 80:
|
||
warning_message = f"警告: 当前系统内存使用率已达 {memory_usage}%!\n建议关闭一些软件后再运行,继续运行可能检测效果不够准确"
|
||
status.update(f"[yellow]{warning_message}[/yellow]")
|
||
|
||
# 显示确认对话框
|
||
def confirm_callback():
|
||
self.show_memory_test_warning()
|
||
|
||
self.push_screen(ConfirmDialog(warning_message, confirm_callback))
|
||
else:
|
||
self.show_memory_test_warning()
|
||
|
||
def show_memory_test_warning(self):
|
||
"""显示内存测试警告"""
|
||
warning = "建议关闭所有docker容器以及停用所有应用程序以保证检测的准确性。"
|
||
status = self.query_one("#status")
|
||
status.update(f"[red]{warning}[/red]")
|
||
|
||
def confirm_callback():
|
||
self.run_memory_test()
|
||
|
||
self.push_screen(ConfirmDialog(warning, confirm_callback))
|
||
|
||
def run_memory_test(self) -> None:
|
||
"""执行内存测试"""
|
||
status = self.query_one("#status")
|
||
mem_size = f"{get_test_memory()}M"
|
||
|
||
message = "正在运行内存测试,请勿进行其它操作,如果运行过程中出现死机重启则大概率为内存问题。整个测试过程预计 30-120 分钟 具体根据内存大小,如果需要终止测试请按Ctrl+C或点击停止按钮。"
|
||
status.update(f"[blue]{message}[/blue]")
|
||
|
||
# 更新界面状态
|
||
self.is_testing = True
|
||
|
||
# 使用try/except捕获可能的NoMatches异常
|
||
try:
|
||
stop_button = self.query_one("#stop-test", Button)
|
||
if stop_button:
|
||
stop_button.disabled = False
|
||
|
||
memory_button = self.query_one("#memory-test", Button)
|
||
if memory_button:
|
||
memory_button.disabled = True
|
||
|
||
cpu_button = self.query_one("#cpu-test", Button)
|
||
if cpu_button:
|
||
cpu_button.disabled = True
|
||
except Exception as e:
|
||
# 记录错误但不中断程序
|
||
print(f"更新按钮状态时出错: {str(e)}")
|
||
|
||
# 创建异步任务
|
||
asyncio.create_task(self.do_memory_test(mem_size))
|
||
|
||
async def do_memory_test(self, mem_size):
|
||
"""异步执行内存测试"""
|
||
status = self.query_one("#status")
|
||
|
||
try:
|
||
# 在异步中执行测试
|
||
result = await asyncio.to_thread(run_command, ["sudo", "memtester", mem_size, "1"])
|
||
|
||
if result['status_code'] == 0:
|
||
success_message = "内存测试完成!未发现问题。"
|
||
status.update(f"[green]{success_message}[/green]")
|
||
self.show_success_dialog(success_message)
|
||
else:
|
||
# 检查是否是被用户手动终止的
|
||
if current_process is None and not result['stderr']:
|
||
status.update("[yellow]测试已被用户终止。[/yellow]")
|
||
else:
|
||
error_message = f"内存测试失败!错误信息:{result['stderr']}"
|
||
status.update(f"[red]{error_message}[/red]")
|
||
self.show_error_dialog(error_message)
|
||
|
||
except Exception as e:
|
||
error_message = f"测试过程中发生错误: {str(e)}"
|
||
status.update(f"[red]{error_message}[/red]")
|
||
self.show_error_dialog(error_message)
|
||
finally:
|
||
# 恢复界面状态
|
||
self.is_testing = False
|
||
|
||
# 使用try/except捕获可能的NoMatches异常
|
||
try:
|
||
stop_button = self.query_one("#stop-test", Button)
|
||
if stop_button:
|
||
stop_button.disabled = True
|
||
|
||
memory_button = self.query_one("#memory-test", Button)
|
||
if memory_button:
|
||
memory_button.disabled = False
|
||
|
||
cpu_button = self.query_one("#cpu-test", Button)
|
||
if cpu_button:
|
||
cpu_button.disabled = False
|
||
except Exception as e:
|
||
# 记录错误但不中断程序
|
||
print(f"更新按钮状态时出错: {str(e)}")
|
||
|
||
def start_cpu_test(self) -> None:
|
||
"""开始CPU测试"""
|
||
def input_callback(duration):
|
||
if duration and duration.isdigit() and int(duration) > 0:
|
||
self.run_cpu_test(duration)
|
||
else:
|
||
self.show_error_dialog("请输入有效的时间(秒)!")
|
||
|
||
self.push_screen(InputDialog("请输入 CPU 压测时长 (秒):", "60", input_callback))
|
||
|
||
def run_cpu_test(self, duration):
|
||
"""执行CPU测试"""
|
||
status = self.query_one("#status")
|
||
|
||
message = f"正在进行 CPU 压测,持续 {duration} 秒...如需提前结束测试,请按Ctrl+C或点击停止按钮。"
|
||
status.update(f"[blue]{message}[/blue]")
|
||
|
||
# 更新界面状态
|
||
self.is_testing = True
|
||
|
||
# 使用try/except捕获可能的NoMatches异常
|
||
try:
|
||
stop_button = self.query_one("#stop-test", Button)
|
||
if stop_button:
|
||
stop_button.disabled = False
|
||
|
||
memory_button = self.query_one("#memory-test", Button)
|
||
if memory_button:
|
||
memory_button.disabled = True
|
||
|
||
cpu_button = self.query_one("#cpu-test", Button)
|
||
if cpu_button:
|
||
cpu_button.disabled = True
|
||
except Exception as e:
|
||
# 记录错误但不中断程序
|
||
print(f"更新按钮状态时出错: {str(e)}")
|
||
|
||
# 创建异步任务
|
||
asyncio.create_task(self.do_cpu_test(duration))
|
||
|
||
async def do_cpu_test(self, duration):
|
||
"""异步执行CPU测试"""
|
||
status = self.query_one("#status")
|
||
|
||
try:
|
||
# 在异步中执行测试
|
||
result = await asyncio.to_thread(run_command, ["stress", "--cpu", "4", "--timeout", duration])
|
||
|
||
if result['status_code'] == 0:
|
||
success_message = "CPU 压测完成!未发现问题。"
|
||
status.update(f"[green]{success_message}[/green]")
|
||
self.show_success_dialog(success_message)
|
||
else:
|
||
# 检查是否是被用户手动终止的
|
||
if current_process is None and not result['stderr']:
|
||
status.update("[yellow]测试已被用户终止。[/yellow]")
|
||
else:
|
||
error_message = f"CPU 压测失败!错误信息:{result['stderr']}"
|
||
status.update(f"[red]{error_message}[/red]")
|
||
self.show_error_dialog(error_message)
|
||
|
||
except Exception as e:
|
||
error_message = f"测试过程中发生错误: {str(e)}"
|
||
status.update(f"[red]{error_message}[/red]")
|
||
self.show_error_dialog(error_message)
|
||
finally:
|
||
# 恢复界面状态
|
||
self.is_testing = False
|
||
|
||
# 使用try/except捕获可能的NoMatches异常
|
||
try:
|
||
stop_button = self.query_one("#stop-test", Button)
|
||
if stop_button:
|
||
stop_button.disabled = True
|
||
|
||
memory_button = self.query_one("#memory-test", Button)
|
||
if memory_button:
|
||
memory_button.disabled = False
|
||
|
||
cpu_button = self.query_one("#cpu-test", Button)
|
||
if cpu_button:
|
||
cpu_button.disabled = False
|
||
except Exception as e:
|
||
# 记录错误但不中断程序
|
||
print(f"更新按钮状态时出错: {str(e)}")
|
||
|
||
def show_success_dialog(self, message: str) -> None:
|
||
"""显示成功对话框"""
|
||
self.push_screen(SuccessDialog(message))
|
||
|
||
def show_error_dialog(self, message: str) -> None:
|
||
"""显示错误对话框"""
|
||
self.push_screen(ErrorDialog(message))
|
||
|
||
if __name__ == "__main__":
|
||
args = parse_arguments()
|
||
|
||
# 如果指定了命令行参数,则直接执行相应功能
|
||
if args.memory:
|
||
cli_memory_test()
|
||
sys.exit(0)
|
||
|
||
if args.cpu is not None:
|
||
cli_cpu_test(args.cpu)
|
||
sys.exit(0)
|
||
|
||
# 如果没有指定命令行参数,则启动图形界面(如果textual可用)
|
||
if HAS_TEXTUAL:
|
||
app = SystemHealthApp()
|
||
app.run()
|
||
else:
|
||
# 这种情况不应该发生,因为在导入时已经处理了,但为了代码完整性保留
|
||
print("错误: 未安装textual库,无法启动图形界面。")
|
||
print("您可以通过命令行参数使用此脚本的核心功能:")
|
||
print(" 内存测试: python self_inspection.py --memory")
|
||
print(" CPU测试: python self_inspection.py --cpu [测试时长(秒)]")
|
||
print(" 查看帮助: python self_inspection.py -h")
|
||
sys.exit(1) |