#!/usr/bin/env node/*** 启动后台进程脚本** 功能:* - 调用 process-manager.mjs 清理旧进程* - 构建项目(如果需要)* - 启动 Admin 服务(Admin 会自动启动 Bridge 子进程)*/import fs from 'node:fs';import path from 'node:path';import process from 'node:process';import { spawn, spawnSync } from 'node:child_process';import { fileURLToPath } from 'node:url';const scriptFile = fileURLToPath(import.meta.url);const scriptDir = path.dirname(scriptFile);const rootDir = path.resolve(scriptDir, '..');const logsDir = path.join(rootDir, 'logs');const pidFile = path.join(logsDir, 'bridge.pid');const outLog = path.join(logsDir, 'service.log');const errLog = path.join(logsDir, 'service.err');const adminEntryFile = path.join(rootDir, 'dist', 'admin', 'index.js');const processManagerPath = path.join(rootDir, 'scripts', 'process-manager.mjs');// 是否跳过 opencode serve 启动(用于已由外部管理 opencode 的场景)const skipOpencodeStart = process.argv.includes('--no-opencode');function isWindows() {return process.platform === 'win32';}function getNpmCommandVariants(args) {const variants = [];const npmExecPath = process.env.npm_execpath;if (npmExecPath) {variants.push({command: process.execPath,args: [npmExecPath, ...args],});}variants.push({ command: 'npm', args });if (isWindows()) {variants.push({ command: 'npm.cmd', args });variants.push({ command: 'npm.exe', args });}const seen = new Set();const uniqueVariants = [];for (const variant of variants) {const key = `${variant.command}::${variant.args.join('\u0000')}`;if (seen.has(key)) {continue;}seen.add(key);uniqueVariants.push(variant);}return uniqueVariants;}function runNpm(args) {const variants = getNpmCommandVariants(args);let lastResult = null;for (const variant of variants) {const result = spawnSync(variant.command, variant.args, {cwd: rootDir,stdio: 'inherit',windowsHide: isWindows(),});if (result.error) {lastResult = result;continue;}if (result.status === 0) {return result;}lastResult = result;}return lastResult;}function ensureLogDir() {fs.mkdirSync(logsDir, { recursive: true });}function ensureBuildIfMissing() {const webEntryFile = path.join(rootDir, 'dist', 'public', 'index.html');const backendMissing = !fs.existsSync(adminEntryFile);const frontendMissing = !fs.existsSync(webEntryFile);if (!backendMissing && !frontendMissing) {return;}if (backendMissing && frontendMissing) {console.log('[start] 未检测到构建产物,开始自动全量构建');} else if (backendMissing) {console.log('[start] 未检测到 dist/admin/index.js,开始自动构建');} else {console.log('[start] 未检测到 dist/public/index.html,开始自动构建前端控制台');}const result = runNpm(['run', 'build:all']);if (!result || result.error || result.status !== 0) {console.error('[start] 构建失败,启动中止');process.exit(result?.status ?? 1);}}function startAdmin() {const stdoutFd = fs.openSync(outLog, 'a');const stderrFd = fs.openSync(errLog, 'a');const child = spawn(process.execPath, [adminEntryFile], {cwd: rootDir,detached: true,stdio: ['ignore', stdoutFd, stderrFd],windowsHide: isWindows(),});child.unref();fs.closeSync(stdoutFd);fs.closeSync(stderrFd);fs.writeFileSync(pidFile, String(child.pid), 'utf-8');console.log(`[start] 启动成功,PID=${child.pid}`);console.log(`[start] 日志文件:${outLog}`);}function sleep(ms) {const end = Date.now() + ms;while (Date.now() < end) {// 忙等待}}function runProcessManager(args, options = {}) {const result = spawnSync(process.execPath, [processManagerPath, ...args], {stdio: 'pipe',encoding: 'utf-8',windowsHide: isWindows(),...options,});if (result.stdout?.trim()) console.log(result.stdout.trim());if (result.stderr?.trim()) console.error(result.stderr.trim());return result;}function main() {ensureLogDir();// 0. 启动 opencode serve(幂等 - 如果已在运行则跳过)if (skipOpencodeStart) {console.log('[start] 跳过 opencode serve 启动(--no-opencode)');} else {console.log('[start] 启动 opencode serve...');const opencodeResult = runProcessManager(['start-opencode']);if (opencodeResult.status !== 0) {console.warn('[start] 警告:opencode serve 启动失败,继续启动 Bridge(可稍后手动启动 opencode)');}}// 1. 调用进程管理工具清理旧 Bridge 进程(不传递 --exclude-self,因为这是独立调用)console.log('[start] 清理旧 Bridge 进程...');runProcessManager(['kill-bridge']);// 2. 等待 3 秒,确保旧进程完全退出console.log('[start] 等待进程退出...');sleep(3000);ensureBuildIfMissing();// 3. 启动 Admin 服务(Admin 会自动启动 Bridge 子进程)startAdmin();}main();
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。