tt-help-cli-ycl 1.4.103 → 1.4.104
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/watchdog/agent.js +0 -1
- package/src/watchdog/upgrader.js +26 -35
package/package.json
CHANGED
package/src/watchdog/agent.js
CHANGED
package/src/watchdog/upgrader.js
CHANGED
|
@@ -197,33 +197,32 @@ function openLogFile(prefix, label, what) {
|
|
|
197
197
|
}
|
|
198
198
|
|
|
199
199
|
/**
|
|
200
|
-
* spawn 子进程(升级器 U / 新版 watchdog
|
|
200
|
+
* spawn 子进程(升级器 U / 新版 watchdog 共用),一律 detached 独立控制台:
|
|
201
201
|
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
202
|
+
* 背景(Windows 实测教训):旧 watchdog 被杀后旧 cmd /k 窗口的控制台句柄状态被破坏,
|
|
203
|
+
* 任何 inherit 旧窗口的子进程(升级器 U)再 spawn 新进程都会崩溃——
|
|
204
|
+
* 升级日志停在「新版 watchdog 日志」,无「已启动/失败」(211 三次复现)。
|
|
205
|
+
* 因此升级链上的子进程全部 detached + 独立日志落盘,与旧窗口完全解耦。
|
|
204
206
|
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
* 旧 watchdog 被杀不影响新版(不依赖旧窗口控制台,Windows 实测可靠)。
|
|
209
|
-
* - windowsHide: false → 允许弹出该控制台窗口(前端可见)。
|
|
210
|
-
* - stdio 独立日志文件 → 进程退出后日志可查。
|
|
207
|
+
* - U(升级器):hide: true → 后台运行不弹窗,stdout/stderr 落盘 logFd
|
|
208
|
+
* - 新版 watchdog:hide 默认 false → Windows 上 detached 子进程拥有【独立控制台窗口】
|
|
209
|
+
* (前端可见),运维远程(RDP/桌面)可看日志,旧 watchdog 被杀不影响新版
|
|
211
210
|
*
|
|
212
211
|
* @param {string[]} args 子进程完整参数(node 脚本路径 + 参数)
|
|
213
|
-
* @param {{
|
|
212
|
+
* @param {{logFd?: number, hide?: boolean}} opts
|
|
214
213
|
* @returns {import("child_process").ChildProcess}
|
|
215
214
|
*/
|
|
216
|
-
function spawnChild(args, {
|
|
215
|
+
function spawnChild(args, { logFd, hide = false } = {}) {
|
|
217
216
|
const child = spawn(process.execPath, args, {
|
|
218
|
-
detached:
|
|
219
|
-
stdio:
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
217
|
+
detached: true,
|
|
218
|
+
stdio: ["ignore", logFd || "ignore", logFd || "ignore"],
|
|
219
|
+
windowsHide: hide,
|
|
220
|
+
});
|
|
221
|
+
child.unref();
|
|
222
|
+
// 防 spawn 失败(如目标脚本缺失)触发未监听的 'error' 事件静默崩溃;日志落盘可查
|
|
223
|
+
child.on("error", (err) => {
|
|
224
|
+
console.error(`[spawn] 子进程启动失败: ${err.message}`);
|
|
225
225
|
});
|
|
226
|
-
if (!interactive) child.unref();
|
|
227
226
|
return child;
|
|
228
227
|
}
|
|
229
228
|
|
|
@@ -271,7 +270,6 @@ function buildWatchdogArgs({ serverUrl, clientId, intervalSec, noDaemon }) {
|
|
|
271
270
|
*/
|
|
272
271
|
export async function runUpgradeMode(argv) {
|
|
273
272
|
const get = (f) => (argv.includes(f) ? argv[argv.indexOf(f) + 1] : undefined);
|
|
274
|
-
const interactive = argv.includes("--interactive");
|
|
275
273
|
const serverUrl = get("--server");
|
|
276
274
|
const clientId = get("--client-id");
|
|
277
275
|
const intervalSec = parseInt(get("--interval"), 10) || 15;
|
|
@@ -314,13 +312,8 @@ export async function runUpgradeMode(argv) {
|
|
|
314
312
|
}
|
|
315
313
|
|
|
316
314
|
// 4) 旧进程已退,启新版 watchdog
|
|
317
|
-
// 新版永远 detached + windowsHide:false
|
|
318
|
-
//
|
|
319
|
-
// → 新版在【新开的前端 cmd 窗口】运行,运维远程(RDP/桌面)可看日志
|
|
320
|
-
// - 不接管旧 cmd /k 窗口(interactive inherit 在 Windows 实测三次失败,
|
|
321
|
-
// 旧窗口控制台在旧 watchdog 被杀后不可复用)
|
|
322
|
-
// - 独立日志文件,进程退出后可查
|
|
323
|
-
// U 本身仍按 interactive 透传(旧窗口显示升级日志,不阻断)
|
|
315
|
+
// 新版永远 detached + windowsHide:false → 独立控制台窗口(前端可见),
|
|
316
|
+
// 与旧 cmd /k 窗口解耦(旧窗口控制台在旧 watchdog 被杀后不可复用)
|
|
324
317
|
console.error(`[upgrade-proc] 启动新版 watchdog ...`);
|
|
325
318
|
const cliPath = join(__dirname, "..", "..", "cli.js");
|
|
326
319
|
const args = buildWatchdogArgs({
|
|
@@ -336,8 +329,8 @@ export async function runUpgradeMode(argv) {
|
|
|
336
329
|
);
|
|
337
330
|
let child;
|
|
338
331
|
try {
|
|
339
|
-
//
|
|
340
|
-
child = spawnChild([cliPath, ...args], {
|
|
332
|
+
// 新版永远独立控制台窗口(hide 默认 false),不再继承旧 cmd /k 窗口
|
|
333
|
+
child = spawnChild([cliPath, ...args], { logFd });
|
|
341
334
|
console.error(`[upgrade-proc] 新版 watchdog 已启动 (pid=${child.pid})`);
|
|
342
335
|
} catch (e) {
|
|
343
336
|
console.error(`[upgrade-proc] 新版 watchdog 启动失败: ${e.message}`);
|
|
@@ -363,7 +356,8 @@ export async function runUpgradeMode(argv) {
|
|
|
363
356
|
/**
|
|
364
357
|
* 旧 watchdog 调用:spawn 独立升级器(fire-and-forget,不等待、不写中间文件)
|
|
365
358
|
* 升级器负责「下载 → 验证 → 杀旧 → 启新」(见 runUpgradeMode);本进程收到 SIGTERM 优雅退出。
|
|
366
|
-
*
|
|
359
|
+
* U 永远 detached 后台运行(stdout/stderr 落盘),不 inherit 旧 cmd /k 窗口——
|
|
360
|
+
* 旧 watchdog 被杀后旧窗口控制台状态被破坏,U 若 inherit 旧窗口再 spawn 新版即崩(211 实测)。
|
|
367
361
|
* @returns {import("child_process").ChildProcess|null} 升级器子进程(spawn 失败返回 null)
|
|
368
362
|
*/
|
|
369
363
|
export function spawnUpgrader({
|
|
@@ -371,7 +365,6 @@ export function spawnUpgrader({
|
|
|
371
365
|
clientId,
|
|
372
366
|
intervalSec = 15,
|
|
373
367
|
spawnDaemon = true,
|
|
374
|
-
interactive = false,
|
|
375
368
|
oldPid = 0,
|
|
376
369
|
} = {}) {
|
|
377
370
|
const upgraderPath = fileURLToPath(import.meta.url);
|
|
@@ -380,13 +373,11 @@ export function spawnUpgrader({
|
|
|
380
373
|
if (clientId) args.push("--client-id", clientId);
|
|
381
374
|
args.push("--interval", String(intervalSec));
|
|
382
375
|
if (!spawnDaemon) args.push("--no-daemon");
|
|
383
|
-
if (interactive) args.push("--interactive");
|
|
384
376
|
|
|
385
377
|
const logFd = openLogFile("tt-help-upgrader", "watchdog", "升级程序日志");
|
|
386
378
|
try {
|
|
387
|
-
// U
|
|
388
|
-
|
|
389
|
-
return spawnChild([upgraderPath, ...args], { interactive, logFd });
|
|
379
|
+
// U 永远 detached 后台(日志落盘),与旧窗口解耦(见上方注释)
|
|
380
|
+
return spawnChild([upgraderPath, ...args], { logFd, hide: true });
|
|
390
381
|
} catch (e) {
|
|
391
382
|
console.error(`[watchdog] 升级程序启动失败: ${e.message}`);
|
|
392
383
|
return null;
|