优雅关闭,复归!(感谢豆包)

pull/1001/head
SnowindMe 2025-05-29 06:43:09 +08:00
parent 280feec228
commit fc306d5990
1 changed files with 61 additions and 15 deletions

76
bot.py
View File

@ -2,10 +2,13 @@ import asyncio
import hashlib
import os
import sys
# import shutil
from pathlib import Path
import time
import platform
import traceback
import signal
from dotenv import load_dotenv
from src.common.logger_manager import get_logger
@ -14,7 +17,8 @@ from src.common.crash_logger import install_crash_handler
from src.main import MainSystem
from rich.traceback import install
from src.manager.async_task_manager import async_task_manager
from asyncio import CancelledError
# from src.manager.async_task_manager import async_task_manager
install(extra_lines=3)
@ -34,15 +38,19 @@ driver = None
app = None
loop = None
# shutdown_requested = False # 新增全局变量
shutdown_requested = False # 新增全局变量
async def request_shutdown() -> bool:
"""请求关闭程序"""
global shutdown_requested
if shutdown_requested:
return True
shutdown_requested = True
try:
if loop and not loop.is_closed():
try:
loop.run_until_complete(graceful_shutdown())
await graceful_shutdown()
except Exception as ge: # 捕捉优雅关闭时可能发生的错误
logger.error(f"优雅关闭时发生错误: {ge}")
return False
@ -65,6 +73,38 @@ def easter_egg():
print(rainbow_text)
# def init_config():
# # 初次启动检测
# if not os.path.exists("config/bot_config.toml"):
# logger.warning("检测到bot_config.toml不存在正在从模板复制")
# # 检查config目录是否存在
# if not os.path.exists("config"):
# os.makedirs("config")
# logger.info("创建config目录")
# shutil.copy("template/bot_config_template.toml", "config/bot_config.toml")
# logger.info("复制完成请修改config/bot_config.toml和.env中的配置后重新启动")
# if not os.path.exists("config/lpmm_config.toml"):
# logger.warning("检测到lpmm_config.toml不存在正在从模板复制")
# # 检查config目录是否存在
# if not os.path.exists("config"):
# os.makedirs("config")
# logger.info("创建config目录")
# shutil.copy("template/lpmm_config_template.toml", "config/lpmm_config.toml")
# logger.info("复制完成请修改config/lpmm_config.toml和.env中的配置后重新启动")
# def init_env():
# # 检测.env文件是否存在
# if not os.path.exists(".env"):
# logger.error("检测到.env文件不存在")
# shutil.copy("template/template.env", "./.env")
# logger.info("已从template/template.env复制创建.env请修改配置后重新启动")
def load_env():
# 直接加载生产环境变量配置
if os.path.exists(".env"):
@ -109,10 +149,7 @@ def scan_provider(env_config: dict):
async def graceful_shutdown():
try:
logger.info("正在优雅关闭麦麦...")
# 停止所有异步任务
await async_task_manager.stop_and_wait_all_tasks()
# await async_task_manager.stop_and_wait_all_tasks()
tasks = [t for t in asyncio.all_tasks() if t is not asyncio.current_task()]
for task in tasks:
task.cancel()
@ -208,9 +245,9 @@ def raw_main():
check_eula()
print("检查EULA和隐私条款完成")
easter_egg()
# init_config()
# init_env()
load_env()
env_config = {key: os.getenv(key) for key in os.environ}
@ -220,6 +257,11 @@ def raw_main():
return MainSystem()
def signal_handler(sig, frame):
"""信号处理函数捕获SIGINT和SIGTERM信号"""
loop.create_task(request_shutdown())
if __name__ == "__main__":
exit_code = 0 # 用于记录程序最终的退出状态
try:
@ -230,18 +272,22 @@ if __name__ == "__main__":
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
# 新增:设置信号处理
if platform.system().lower() != "windows":
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
try:
# 执行初始化和任务调度
loop.run_until_complete(main_system.initialize())
loop.run_until_complete(main_system.schedule_tasks())
loop.run_forever()
except KeyboardInterrupt:
# loop.run_until_complete(global_api.stop())
logger.warning("收到中断信号,正在优雅关闭...")
if loop and not loop.is_closed():
try:
loop.run_until_complete(graceful_shutdown())
except Exception as ge: # 捕捉优雅关闭时可能发生的错误
logger.error(f"优雅关闭时发生错误: {ge}")
try:
loop.run_until_complete(request_shutdown())
except CancelledError as e:
logger.error(f"优雅关闭时发生错误: {e}")
# 新增:检测外部请求关闭
# except Exception as e: # 将主异常捕获移到外层 try...except