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}`)), // 新增一个专门用于子进程输出的 logger subprocess: (message) => console.log(chalk.gray(`[ProxyBinary] ${message}`)), }; class ProxyServer { constructor() { this.proxyProcess = null; this.platform = process.env.PROXY_SERVER_PLATFORM || 'auto'; this.port = process.env.PROXY_SERVER_PORT || 10655; // ***【修改 1】*** 移除了 this.logPath 和 this.logStream this.enabled = process.env.ENABLE_PROXY_SERVER === 'true'; this.proxyAuthToken = process.env.PROXY_AUTH_TOKEN || 'default_token'; } // 获取当前系统平台 (无变化) detectPlatform() { if (this.platform !== 'auto') { return this.platform; } const platform = os.platform(); const arch = os.arch(); if (platform === 'win32') return 'windows'; if (platform === 'linux') return (arch === 'arm64' ? 'android' : 'linux'); if (platform === 'android') return 'android'; logger.warning(`未知平台: ${platform}, ${arch}, 默认使用linux版本`); return 'linux'; } // 获取代理服务器可执行文件路径 (无变化) getProxyServerPath() { const platform = this.detectPlatform(); const isProduction = process.env.NODE_ENV === 'production'; const proxyDir = isProduction ? '/tmp/proxy' : join(__dirname, 'proxy'); logger.info(`环境: ${isProduction ? 'Production' : 'Development'}, 代理二进制目录: ${proxyDir}`); 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 || !fs.existsSync(proxyServerPath)) { logger.error(`代理二进制文件不存在于路径: ${proxyServerPath || '未知'}`); return; } try { // ***【修改 2】*** 移除了所有与文件日志相关的代码 // 启动代理服务器进程 this.proxyProcess = spawn(proxyServerPath, [ '--port', this.port.toString(), '--token', this.proxyAuthToken ], { stdio: ['ignore', 'pipe', 'pipe'], detached: false }); // ***【修改 3】*** 将子进程的输出直接打印到控制台 if (this.proxyProcess.stdout) { this.proxyProcess.stdout.on('data', (data) => { logger.subprocess(data.toString().trim()); }); } if (this.proxyProcess.stderr) { this.proxyProcess.stderr.on('data', (data) => { logger.error(`[ProxyBinary-Error] ${data.toString().trim()}`); }); } this.proxyProcess.on('error', (err) => { logger.error(`代理服务器启动失败: ${err.message}`); this.proxyProcess = null; }); this.proxyProcess.on('exit', (code, signal) => { logger.info(`代理服务器已退出,退出码: ${code}, 信号: ${signal}`); this.proxyProcess = null; }); await new Promise(resolve => setTimeout(resolve, 1000)); if (this.proxyProcess && this.proxyProcess.exitCode === null) { logger.success(`代理服务器已启动,端口: ${this.port}`); return true; } else { logger.error('代理服务器启动失败或立即退出。'); return false; } } catch (error) { logger.error(`启动代理服务器时出错: ${error.message}`); return false; } } // 停止代理服务器 (无变化) stop() { if (!this.proxyProcess) return; try { if (this.detectPlatform() === 'windows' && this.proxyProcess.pid) { spawn('taskkill', ['/pid', this.proxyProcess.pid, '/f', '/t']); } else { this.proxyProcess.kill('SIGTERM'); } logger.success('代理服务器已停止'); } catch (error) { logger.error(`停止代理服务器时出错: ${error.message}`); } finally { this.proxyProcess = null; } } } // 创建单例 const proxyServer = new ProxyServer(); // 导出 export { proxyServer };