import { spawn } from 'child_process'; import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; import fs from 'fs'; import os from 'os'; import dotenv from 'dotenv'; import chalk from 'chalk'; // 获取当前文件的目录路径 const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); // 加载环境变量 dotenv.config({ path: join(dirname(__dirname), '.env') }); // 日志配置 const logger = { info: (message) => console.log(chalk.blue(`[ProxyServer] ${message}`)), error: (message) => console.error(chalk.red(`[ProxyServer] ${message}`)), warning: (message) => console.warn(chalk.yellow(`[ProxyServer] ${message}`)), success: (message) => console.log(chalk.green(`[ProxyServer] ${message}`)), }; class ProxyServer { constructor() { this.proxyProcess = null; this.platform = process.env.PROXY_SERVER_PLATFORM || 'auto'; this.port = process.env.PROXY_SERVER_PORT || 10655; this.logPath = process.env.PROXY_SERVER_LOG_PATH || '/tmp/proxy_server.log'; this.enabled = process.env.ENABLE_PROXY_SERVER === 'true'; this.proxyAuthToken = process.env.PROXY_AUTH_TOKEN || 'default_token'; this.logStream = null; } // 获取当前系统平台 detectPlatform() { if (this.platform !== 'auto') { return this.platform; } const platform = os.platform(); const arch = os.arch(); if (platform === 'win32') { return 'windows'; } else if (platform === 'linux') { if (arch === 'arm64') { return 'android'; } else { return 'linux'; } } else if (platform === 'android') { return 'android'; } else { logger.warning(`未知平台: ${platform}, ${arch}, 默认使用linux版本`); return 'linux'; } } // 获取代理服务器可执行文件路径 getProxyServerPath() { const platform = this.detectPlatform(); const proxyDir = join(__dirname, 'proxy'); switch (platform) { case 'windows': return join(proxyDir, 'chrome_proxy_server_windows_amd64.exe'); case 'linux': return join(proxyDir, 'chrome_proxy_server_linux_amd64'); case 'android': return join(proxyDir, 'chrome_proxy_server_android_arm64'); default: logger.error(`不支持的平台: ${platform}`); return null; } } // 启动代理服务器 async start() { if (!this.enabled) { logger.info('代理服务器未启用,跳过启动'); return; } if (this.proxyProcess) { logger.warning('代理服务器已经在运行中'); return; } const proxyServerPath = this.getProxyServerPath(); if (!proxyServerPath) { logger.error('无法获取代理服务器路径'); return; } try { // 确保可执行文件有执行权限(在Linux/Android上) // 在Hugging Face环境中,文件权限应在Dockerfile中设置,运行时修改可能会失败 // if (this.detectPlatform() !== 'windows') { // try { // fs.chmodSync(proxyServerPath, 0o755); // } catch (err) { // logger.warning(`无法设置执行权限: ${err.message}`); // } // } // 创建日志文件 this.logStream = fs.createWriteStream(this.logPath, { flags: 'a' }); // 修复 stdio 参数问题 // 启动代理服务器进程 this.proxyProcess = spawn(proxyServerPath, [ '--port', this.port.toString(), '--token', this.proxyAuthToken ], { stdio: ['ignore', 'pipe', 'pipe'], // 使用pipe而不是直接传递流 detached: false }); // 将进程的输出重定向到日志文件 if (this.proxyProcess.stdout) { this.proxyProcess.stdout.pipe(this.logStream); } if (this.proxyProcess.stderr) { this.proxyProcess.stderr.pipe(this.logStream); } // 设置进程事件处理 this.proxyProcess.on('error', (err) => { logger.error(`代理服务器启动失败: ${err.message}`); this.proxyProcess = null; if (this.logStream) { this.logStream.end(); this.logStream = null; } }); this.proxyProcess.on('exit', (code, signal) => { logger.info(`代理服务器已退出,退出码: ${code}, 信号: ${signal}`); this.proxyProcess = null; if (this.logStream) { this.logStream.end(); this.logStream = null; } }); // 等待一段时间,确保服务器启动 await new Promise(resolve => setTimeout(resolve, 1000)); if (this.proxyProcess && this.proxyProcess.exitCode === null) { logger.success(`代理服务器已启动,端口: ${this.port}, 日志文件: ${this.logPath}`); return true; } else { logger.error('代理服务器启动失败'); if (this.logStream) { this.logStream.end(); this.logStream = null; } return false; } } catch (error) { logger.error(`启动代理服务器时出错: ${error.message}`); if (this.logStream) { this.logStream.end(); this.logStream = null; } return false; } } // 停止代理服务器 stop() { if (!this.proxyProcess) { //logger.info('代理服务器已关闭'); return; } try { // 在Windows上使用taskkill确保子进程也被终止 if (this.detectPlatform() === 'windows' && this.proxyProcess.pid) { spawn('taskkill', ['/pid', this.proxyProcess.pid, '/f', '/t']); } else { // 在Linux/Android上使用kill信号 this.proxyProcess.kill('SIGTERM'); } logger.success('代理服务器已停止'); } catch (error) { logger.error(`停止代理服务器时出错: ${error.message}`); } finally { this.proxyProcess = null; if (this.logStream) { this.logStream.end(); this.logStream = null; } } } } // 创建单例 const proxyServer = new ProxyServer(); // 导出 export { proxyServer };