优化由于WebUI启动时端口占用导致异常退出没有提示的问题

pull/1420/head
墨梓柒 2025-12-08 18:48:11 +08:00
parent 1bb5ceff39
commit 00c1e7d601
No known key found for this signature in database
GPG Key ID: 4A65B9DBA35F7635
5 changed files with 2863 additions and 25 deletions

2
bot.py
View File

@ -143,7 +143,7 @@ def print_opensource_notice():
"", "",
f"{Fore.WHITE} 官方仓库: {Fore.BLUE}https://github.com/MaiM-with-u/MaiBot {Style.RESET_ALL}", f"{Fore.WHITE} 官方仓库: {Fore.BLUE}https://github.com/MaiM-with-u/MaiBot {Style.RESET_ALL}",
f"{Fore.WHITE} 官方文档: {Fore.BLUE}https://docs.mai-mai.org {Style.RESET_ALL}", f"{Fore.WHITE} 官方文档: {Fore.BLUE}https://docs.mai-mai.org {Style.RESET_ALL}",
f"{Fore.WHITE} 官方群聊: {Fore.BLUE}766798517{Style.RESET_ALL}", f"{Fore.WHITE} 官方群聊: {Fore.BLUE}1006149251{Style.RESET_ALL}",
f"{Fore.CYAN}{'' * 70}{Style.RESET_ALL}", f"{Fore.CYAN}{'' * 70}{Style.RESET_ALL}",
f"{Fore.RED} ⚠ 将本软件作为「商品」倒卖、隐瞒开源性质均违反协议!{Style.RESET_ALL}", f"{Fore.RED} ⚠ 将本软件作为「商品」倒卖、隐瞒开源性质均违反协议!{Style.RESET_ALL}",
f"{Fore.CYAN}{'' * 70}{Style.RESET_ALL}", f"{Fore.CYAN}{'' * 70}{Style.RESET_ALL}",

View File

@ -1,6 +1,6 @@
[project] [project]
name = "MaiBot" name = "MaiBot"
version = "0.11.0" version = "0.11.6"
description = "MaiCore 是一个基于大语言模型的可交互智能体" description = "MaiCore 是一个基于大语言模型的可交互智能体"
requires-python = ">=3.10" requires-python = ">=3.10"
dependencies = [ dependencies = [
@ -38,6 +38,10 @@ dependencies = [
] ]
[tool.uv]
index-url = "https://pypi.tuna.tsinghua.edu.cn/simple"
[tool.ruff] [tool.ruff]
include = ["*.py"] include = ["*.py"]

View File

@ -52,23 +52,11 @@ class MainSystem:
logger.info("WebUI 已禁用") logger.info("WebUI 已禁用")
return return
webui_mode = os.getenv("WEBUI_MODE", "production").lower()
try: try:
from src.webui.webui_server import get_webui_server from src.webui.webui_server import get_webui_server
self.webui_server = get_webui_server() self.webui_server = get_webui_server()
if webui_mode == "development":
logger.info("📝 WebUI 开发模式已启用")
logger.info("🌐 后端 API 将运行在 http://0.0.0.0:8001")
logger.info("💡 请手动启动前端开发服务器: cd MaiBot-Dashboard && bun dev")
logger.info("💡 前端将运行在 http://localhost:7999")
else:
logger.info("✅ WebUI 生产模式已启用")
logger.info("🌐 WebUI 将运行在 http://0.0.0.0:8001")
logger.info("💡 请确保已构建前端: cd MaiBot-Dashboard && bun run build")
except Exception as e: except Exception as e:
logger.error(f"❌ 初始化 WebUI 服务器失败: {e}") logger.error(f"❌ 初始化 WebUI 服务器失败: {e}")

View File

@ -109,23 +109,14 @@ class WebUIServer:
# 导入所有 WebUI 路由 # 导入所有 WebUI 路由
from src.webui.routes import router as webui_router from src.webui.routes import router as webui_router
from src.webui.logs_ws import router as logs_router from src.webui.logs_ws import router as logs_router
logger.info("开始导入 knowledge_routes...")
from src.webui.knowledge_routes import router as knowledge_router from src.webui.knowledge_routes import router as knowledge_router
logger.info("knowledge_routes 导入成功")
# 导入本地聊天室路由 # 导入本地聊天室路由
from src.webui.chat_routes import router as chat_router from src.webui.chat_routes import router as chat_router
logger.info("chat_routes 导入成功")
# 注册路由 # 注册路由
self.app.include_router(webui_router) self.app.include_router(webui_router)
self.app.include_router(logs_router) self.app.include_router(logs_router)
self.app.include_router(knowledge_router) self.app.include_router(knowledge_router)
self.app.include_router(chat_router) self.app.include_router(chat_router)
logger.info(f"knowledge_router 路由前缀: {knowledge_router.prefix}")
logger.info("✅ WebUI API 路由已注册") logger.info("✅ WebUI API 路由已注册")
except Exception as e: except Exception as e:
@ -133,6 +124,16 @@ class WebUIServer:
async def start(self): async def start(self):
"""启动服务器""" """启动服务器"""
# 预先检查端口是否可用
if not self._check_port_available():
error_msg = f"❌ WebUI 服务器启动失败: 端口 {self.port} 已被占用"
logger.error(error_msg)
logger.error(f"💡 请检查是否有其他程序正在使用端口 {self.port}")
logger.error("💡 可以通过环境变量 WEBUI_PORT 修改 WebUI 端口")
logger.error(f"💡 Windows 用户可以运行: netstat -ano | findstr :{self.port}")
logger.error(f"💡 Linux/Mac 用户可以运行: lsof -i :{self.port}")
raise OSError(f"端口 {self.port} 已被占用,无法启动 WebUI 服务器")
config = Config( config = Config(
app=self.app, app=self.app,
host=self.host, host=self.host,
@ -149,9 +150,30 @@ class WebUIServer:
try: try:
await self._server.serve() await self._server.serve()
except Exception as e: except OSError as e:
logger.error(f"❌ WebUI 服务器运行错误: {e}") # 处理端口绑定相关的错误
if "address already in use" in str(e).lower() or e.errno in (98, 10048): # 98: Linux, 10048: Windows
logger.error(f"❌ WebUI 服务器启动失败: 端口 {self.port} 已被占用")
logger.error(f"💡 请检查是否有其他程序正在使用端口 {self.port}")
logger.error("💡 可以通过环境变量 WEBUI_PORT 修改 WebUI 端口")
else:
logger.error(f"❌ WebUI 服务器启动失败 (网络错误): {e}")
raise raise
except Exception as e:
logger.error(f"❌ WebUI 服务器运行错误: {e}", exc_info=True)
raise
def _check_port_available(self) -> bool:
"""检查端口是否可用"""
import socket
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(1)
# 尝试绑定端口
s.bind((self.host if self.host != "0.0.0.0" else "127.0.0.1", self.port))
return True
except OSError:
return False
async def shutdown(self): async def shutdown(self):
"""关闭服务器""" """关闭服务器"""

2824
uv.lock 100644

File diff suppressed because it is too large Load Diff