tt-help-cli-ycl 1.4.102 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tt-help-cli-ycl",
3
- "version": "1.4.102",
3
+ "version": "1.4.104",
4
4
  "description": "TikTok user & video data scraper - extract ttSeller, verified, locationCreated from HTML source",
5
5
  "type": "module",
6
6
  "bin": {
@@ -592,7 +592,6 @@ export class WatchdogAgent {
592
592
  clientId: this.clientId,
593
593
  intervalSec: Math.max(5, Math.round(this.intervalMs / 1000)),
594
594
  spawnDaemon: this.spawnDaemon,
595
- interactive: !!process.stdout.isTTY,
596
595
  oldPid: process.pid,
597
596
  };
598
597
  }
@@ -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
- * interactive(仅用于 U):stdio inherit,继承 cmd /k 前端窗口,
203
- * 让运维在前端窗口看升级过程日志([upgrade-proc])。
202
+ * 背景(Windows 实测教训):旧 watchdog 被杀后旧 cmd /k 窗口的控制台句柄状态被破坏,
203
+ * 任何 inherit 旧窗口的子进程(升级器 U)再 spawn 新进程都会崩溃——
204
+ * 升级日志停在「新版 watchdog 日志」,无「已启动/失败」(211 三次复现)。
205
+ * 因此升级链上的子进程全部 detached + 独立日志落盘,与旧窗口完全解耦。
204
206
  *
205
- * 新版 watchdog 一律以非交互方式 spawn(interactive: false):
206
- * - detached: true → Windows 上子进程拥有【独立控制台窗口】(Node 文档语义),
207
- * 即新版在【新开的前端 cmd 窗口】运行,运维远程(RDP/桌面)可看日志;
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 {{interactive?: boolean, logFd?: number}} opts
212
+ * @param {{logFd?: number, hide?: boolean}} opts
214
213
  * @returns {import("child_process").ChildProcess}
215
214
  */
216
- function spawnChild(args, { interactive = false, logFd } = {}) {
215
+ function spawnChild(args, { logFd, hide = false } = {}) {
217
216
  const child = spawn(process.execPath, args, {
218
- detached: !interactive,
219
- stdio: interactive
220
- ? "inherit"
221
- : ["ignore", logFd || "ignore", logFd || "ignore"],
222
- // 关键:windowsHide 恒为 false。新版 detached 时 Windows 自动分配独立控制台窗口
223
- // (前端可见);U interactive 时 inherit 旧窗口也不隐藏。
224
- windowsHide: false,
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
- // - Windows 上 detached:true 时子进程拥有独立控制台窗口(Node 文档语义)
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
- // 新版永远独立控制台窗口,不传 interactive(不再继承旧 cmd /k 窗口)
340
- child = spawnChild([cliPath, ...args], { interactive: false, logFd });
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
- * 非交互时升级器 stdout/stderr 落盘(进程退出后日志不断,可定位问题)
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 按旧 watchdog 的 interactive 透传:cmd /k 前端窗口启动时 U 继承前端窗口(运维可看升级日志),
388
- // 旧 watchdog 非交互启动时 U 自动 detached 后台 + 独立日志
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;