Skip to content

Latest commit

 

History

History
348 lines (263 loc) · 8.46 KB

File metadata and controls

348 lines (263 loc) · 8.46 KB

配置文件路径问题修复

🐛 问题描述

用户报告:"自动配置似乎无效"

现象

  • 通过服务端 GUI 生成的客户端安装包
  • 运行后提示需要配置 CLIENT_ID 和 CLIENT_TOKEN
  • 虽然打包时已生成预配置的 .env 文件,但客户端读取不到

🔍 问题分析

问题1: PyInstaller 打包路径错误

原代码package_builder.py):

datas=[
    (r'{self.client_dir / "agent"}', 'agent'),
    (r'{self.client_dir / ".env"}', '.'),  # ← 错误:引用原始目录
],

问题

  • .env 文件在打包前被生成到 temp_client_dir / "client" / ".env"
  • 但 PyInstaller 引用的是 self.client_dir / ".env"(原始目录)
  • 如果原始目录没有 .env 或内容不对,就会打包错误的配置

问题2: 配置文件路径查找不正确

原代码config.py):

class Config:
    env_file = ".env"  # ← 相对路径,打包后找不到

问题

  • 打包后的文件结构:
    client.exe
    └── _internal/
        ├── agent/
        ├── .env        # 配置文件在这里
        └── ...
    
  • 但相对路径 .env 会在当前工作目录查找
  • 工作目录可能不是程序所在目录
  • 导致找不到配置文件

✅ 解决方案

修复1: 正确打包预配置的 .env 文件

修改package_builder.py):

def _generate_spec_file(self, main_script: str, client_name: str, temp_client_dir: Path) -> str:
    # 使用临时目录中的文件(包含预配置的 .env)
    agent_path = temp_client_dir / "client" / "agent"
    env_path = temp_client_dir / "client" / ".env"  # ← 正确:引用生成的配置
    
    return f"""
    datas=[
        (r'{agent_path}', 'agent'),
        (r'{env_path}', '.'),  # ← 打包生成的配置
    ],
    """

效果

  • 打包时使用临时目录中生成的 .env 文件
  • 该文件包含预配置的 CLIENT_ID 和 CLIENT_TOKEN
  • 确保打包的配置是正确的

修复2: 智能查找配置文件路径

修改config.py):

def get_env_file_path():
    """获取 .env 文件路径,支持打包和开发环境"""
    
    # 如果是 PyInstaller 打包后的环境
    if getattr(sys, 'frozen', False):
        # 打包后,.env 在 _internal 目录
        base_path = Path(sys._MEIPASS)  # PyInstaller 临时目录
        env_path = base_path / ".env"
        if env_path.exists():
            return str(env_path)
        
        # 备选:程序所在目录
        exe_dir = Path(sys.executable).parent
        env_path = exe_dir / ".env"
        if env_path.exists():
            return str(env_path)
    
    # 开发环境:查找多个可能的位置
    possible_paths = [
        Path(".env"),                                      # 当前目录
        Path(__file__).parent.parent / ".env",            # client/.env
        Path(__file__).parent.parent.parent / "client" / ".env",  # 项目根/client/.env
    ]
    
    for path in possible_paths:
        if path.exists():
            return str(path)
    
    return ".env"


class ClientSettings(BaseSettings):
    class Config:
        env_file = get_env_file_path()  # ← 动态获取路径

效果

  • 打包后自动使用 sys._MEIPASS 目录(PyInstaller 特殊变量)
  • 开发环境自动查找多个可能的位置
  • 兼容各种运行环境

📦 打包后的文件结构

客户端名称_client.exe
└── _internal/
    ├── agent/
    │   ├── __init__.py
    │   ├── config.py      # 包含查找逻辑
    │   ├── ws_client.py
    │   └── ...
    ├── .env               # 预配置的文件(包含 CLIENT_ID 和 TOKEN)
    ├── PyQt5/
    └── ...(其他依赖)

运行时

  1. config.py 检测到 sys.frozen = True(打包环境)
  2. 使用 sys._MEIPASS 获取 _internal 目录路径
  3. 拼接得到 .env 文件路径:_internal/.env
  4. 成功加载预配置的 CLIENT_ID 和 TOKEN

🔄 升级步骤

重新生成安装包

必须重新生成才能应用修复:

1. 启动服务端 GUI
   start_server_gui.bat

2. 登录管理平台
   admin / admin123

3. 客户端管理
   → 选择客户端
   → 点击"生成安装包"
   
4. 等待完成(2-5分钟)

5. 测试新安装包
   → 解压 .zip
   → 运行 .exe
   → 应该自动连接,无需配置

✅ 验证方法

测试1: 检查配置是否加载

运行客户端后,应该:

  • ✅ 不提示 "未配置 CLIENT_ID"
  • ✅ 不提示 "未配置 CLIENT_TOKEN"
  • ✅ 自动连接到服务器
  • ✅ 连接状态显示 "🟢 已连接"

测试2: 手动检查配置

如果还有问题,可以添加调试代码:

临时修改client_gui.py):

def load_config(self):
    """加载配置"""
    # 添加调试信息
    print(f"配置文件路径: {settings.Config.env_file}")
    print(f"CLIENT_ID: {settings.CLIENT_ID}")
    print(f"CLIENT_TOKEN: {settings.CLIENT_TOKEN[:10]}..." if settings.CLIENT_TOKEN else "未配置")
    
    self.server_url_input.setText(settings.SERVER_URL)
    # ...

重新打包并运行,查看输出。

测试3: 检查 .env 文件是否打包进去

方式1: 使用 PyInstaller 分析工具

pyi-archive_viewer client.exe
# 输入: toc
# 查找: .env

方式2: 手动检查

运行程序时,在任务管理器中找到进程
查看其临时目录(通常在 %TEMP%)
应该能找到解压出来的 _internal/.env

🎯 最终效果

用户体验

修复前

1. 解压安装包
2. 运行 client.exe
3. 提示需要配置 ❌
4. 需要手动填写 CLIENT_ID 和 TOKEN ❌
5. 点击保存配置 ❌
6. 重新启动客户端 ❌

修复后

1. 解压安装包
2. 运行 client.exe
3. 自动连接服务器 ✅
4. 无需任何配置 ✅
5. 开箱即用 ✅

日志输出示例

修复前

[ERROR] 未配置 CLIENT_ID
[ERROR] 配置验证失败

修复后

[INFO] 加载配置文件: C:\Users\...\AppData\Local\Temp\_MEI123456\.env
[INFO] CLIENT_ID: uuid-xxx-xxx-xxx
[INFO] 连接服务器: http://192.168.1.100:8000
[INFO] WebSocket 连接成功

📝 技术细节

PyInstaller 的 sys._MEIPASS

  • PyInstaller 打包后运行时创建临时目录
  • 所有打包的文件解压到该临时目录
  • sys._MEIPASS 指向该目录
  • 程序退出后自动清理

示例路径

C:\Users\username\AppData\Local\Temp\_MEI123456\

Pydantic Settings 的配置加载

加载顺序

  1. 环境变量(优先级最高)
  2. .env 文件(通过 env_file 指定)
  3. 默认值(类定义中的值)

我们的修改

  • 动态计算 env_file 路径
  • 确保在各种环境中都能找到正确的文件

⚠️ 注意事项

1. 必须重新生成

旧安装包不会自动修复

  • 需要用新代码重新生成
  • 已分发的旧包需要更新

2. 开发环境兼容性

不影响开发

  • 修改后的代码仍然兼容开发环境
  • 可以继续使用 python client_gui.py 运行
  • .env 文件查找逻辑自动适配

3. 配置优先级

环境变量优先

# 即使 .env 文件存在,环境变量仍然优先
set CLIENT_ID=test-id
set CLIENT_TOKEN=test-token
client.exe  # 使用环境变量的值

这个特性可以用于:

  • 临时覆盖配置
  • CI/CD 环境
  • Docker 容器

🔧 故障排查

问题1: 仍然提示未配置

排查步骤

  1. 确认使用的是新生成的安装包
  2. 检查生成时间戳
  3. 删除旧的安装包避免混淆
  4. 查看客户端日志文件

问题2: 配置错误

排查步骤

  1. 检查生成安装包时使用的 CLIENT_ID 和 TOKEN 是否正确
  2. 在服务端 GUI 中查看客户端信息
  3. 确认服务器地址正确

问题3: 连接失败

不是配置问题

  • 配置加载正常
  • 但无法连接服务器
  • 检查网络、防火墙、服务器状态

📚 相关文件

修改的文件

  • server-gui/gui/package_builder.py - 打包逻辑修复
  • client/agent/config.py - 配置加载逻辑修复

相关文档


修复版本: v1.2.1
修复日期: 2025-12-12
影响范围: 所有通过安装包生成功能创建的客户端
解决状态: ✅ 已修复,需重新生成安装包