Files
hospital-front-agent/agent/main.py
T
lianlonggangandClaude 68751c2354 feat: Python 版前置机 Agent 完整实现
- WebSocket 连接 B 端(注册/心跳/指数退避重连)
- 命令分发(10 种远程运维命令)
- 看门狗守护、日志实时流、在线升级含自动回滚
- 修复 main.py 日志格式 style 与占位符不匹配的问题
- 补充 README、配置示例、依赖清单

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-27 11:58:31 +08:00

96 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""Agent 启动入口。
启动方式:
python -m agent.main (源码运行)
hospital-agent.exe PyInstaller 打包后)
职责:
1. WebSocket 主动连接 B 端管理服务器(注册/心跳/命令)
2. 守护主程序(健康探测 + 宕机拉起)
3. 写 PID 文件(pid/hospital-agent.pid
由 WinSW/NSSM Windows 服务守护本进程。
"""
import logging
import os
import signal
import sys
import threading
from agent.config import AgentConfig
from agent.main_app_client import MainAppClient
log = logging.getLogger(__name__)
# 组装阶段先声明,供信号处理器引用
_dispatcher = None
_guard = None
_client = None
def run():
"""主流程:加载配置 → 写 PID → 组装组件 → 启动 → 主线程保活。"""
global _dispatcher, _guard, _client
logging.basicConfig(
level=logging.INFO,
format="{asctime} {levelname} [{name}] {message}",
style="{",
)
# 源码运行时根目录即工作目录,PyInstaller 打包后同理(服务管理器负责设置工作目录)
config = AgentConfig.load()
log.info("Agent 启动:deviceId=%s, server=%s", config.device_id, config.server_url)
# 写 PID 文件
_write_pid_file()
# 组装组件(延迟导入避免环)
from agent.dispatcher import CommandDispatcher
from agent.process_guard import ProcessGuard
from agent.ws_client import AgentClient
main_app_client = MainAppClient(config)
dispatcher = CommandDispatcher(config, main_app_client)
client = AgentClient(config, dispatcher)
dispatcher.set_client(client)
guard = ProcessGuard(config, main_app_client, client)
_dispatcher, _guard, _client = dispatcher, guard, client
# 优雅停机信号处理
signal.signal(signal.SIGINT, _shutdown)
signal.signal(signal.SIGTERM, _shutdown)
client.start()
guard.start()
# 主线程保活
threading.Event().wait()
def _shutdown(signum, frame):
"""优雅停机:释放日志流 → 停守护 → 断连接 → 退出。"""
log.info("Agent 停机中...signal=%s", signum)
if _dispatcher is not None:
_dispatcher.shutdown_log_stream()
if _guard is not None:
_guard.stop()
if _client is not None:
_client.stop()
sys.exit(0)
def _write_pid_file():
"""写 PID 文件(pid/hospital-agent.pid)。"""
try:
os.makedirs("pid", exist_ok=True)
with open(os.path.join("pid", "hospital-agent.pid"), "w", encoding="utf-8") as f:
f.write(str(os.getpid()))
except Exception as e:
log.warning("PID 文件写入失败:%s", e)
if __name__ == "__main__":
run()