fix: use shell background + polling to get dashboard info reliably
Made-with: Cursor
This commit is contained in:
58
lib/frpc.js
58
lib/frpc.js
@@ -16,47 +16,43 @@ const FRPC_CONFIG = path.join(CONFIG_DIR, 'frpc.toml');
|
|||||||
const FRP_VERSION = '0.62.0';
|
const FRP_VERSION = '0.62.0';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 启动 openclaw dashboard(若未运行),等待输出中出现 Dashboard URL,
|
* 启动 openclaw dashboard(后台运行),轮询日志文件等待 Dashboard URL 出现,
|
||||||
* 解析并返回 { dashboard_token, dashboard_port }。
|
* 解析并返回 { dashboard_token, dashboard_port }。
|
||||||
* 超时或命令不存在时返回 {}。
|
* 超时(10s)或命令不存在时返回 {}。
|
||||||
* dashboard 进程会持续运行(不会被 kill)。
|
|
||||||
*/
|
*/
|
||||||
function getDashboardInfo() {
|
function getDashboardInfo() {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
let done = false;
|
const tmpLog = '/tmp/clawd-dashboard.log';
|
||||||
const finish = (result) => {
|
|
||||||
if (!done) { done = true; resolve(result); }
|
|
||||||
};
|
|
||||||
|
|
||||||
// 8 秒内未收到 URL 则放弃
|
// 后台启动 dashboard,输出重定向到日志文件
|
||||||
const timer = setTimeout(() => finish({}), 8000);
|
|
||||||
|
|
||||||
let proc;
|
|
||||||
try {
|
try {
|
||||||
proc = spawn('openclaw', ['dashboard'], {
|
execSync(`openclaw dashboard > ${tmpLog} 2>&1 &`, { shell: true, timeout: 3000 });
|
||||||
stdio: ['ignore', 'pipe', 'pipe'],
|
|
||||||
});
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
clearTimeout(timer);
|
// 已在运行或命令不存在,继续轮询
|
||||||
return finish({});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleLine = (line) => {
|
// 每秒读一次日志文件,最多等 10 秒
|
||||||
const match = line.match(/Dashboard URL:.*:(\d+)\/#token=([a-f0-9]+)/);
|
let attempts = 0;
|
||||||
if (match) {
|
const interval = setInterval(() => {
|
||||||
clearTimeout(timer);
|
attempts++;
|
||||||
const port = parseInt(match[1], 10);
|
try {
|
||||||
const token = match[2];
|
const content = fs.readFileSync(tmpLog, 'utf8');
|
||||||
console.log(`[frpc] openclaw dashboard: port=${port}, token=${token.substring(0, 8)}...`);
|
const match = content.match(/Dashboard URL:.*:(\d+)\/#token=([a-f0-9]+)/);
|
||||||
// 进程继续运行(dashboard 服务),不 kill
|
if (match) {
|
||||||
finish({ dashboard_port: port, dashboard_token: token });
|
clearInterval(interval);
|
||||||
}
|
const port = parseInt(match[1], 10);
|
||||||
};
|
const token = match[2];
|
||||||
|
console.log(`[frpc] openclaw dashboard: port=${port}, token=${token.substring(0, 8)}...`);
|
||||||
|
resolve({ dashboard_port: port, dashboard_token: token });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) { /* 文件暂时不存在 */ }
|
||||||
|
|
||||||
proc.stdout.on('data', d => handleLine(d.toString()));
|
if (attempts >= 10) {
|
||||||
proc.stderr.on('data', d => handleLine(d.toString()));
|
clearInterval(interval);
|
||||||
proc.on('error', () => { clearTimeout(timer); finish({}); });
|
resolve({});
|
||||||
proc.on('exit', () => { clearTimeout(timer); finish({}); });
|
}
|
||||||
|
}, 1000);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user