fix(scripts): 自重启任务纳入卸载清理 —— 修「僵尸任务反复拉起已删文件」
真机发现:`system.agent.restart` 每次重启注册 `nodeagent-selfrestart-<毫秒>`,
而 TASK_WHITELIST 只有 nodeagent/na-gui/nodeagent-console → 卸载后这类任务残留,
会持续尝试拉起已被删除的 agent.mjs。
但它不能当垃圾随手清:**Running 的那一个往往就是当前 agent 的父任务**
(删了会连带杀掉 agent)。故只纳入「卸载清理」判定集合,由调用方在停掉
agent 之后使用。
匹配用严格命名空间 `^nodeagent-selfrestart-\d{6,}$`(纯数字时间戳形态),
不做任何通配;`nodeagent-selfrestart-abc`/前缀不全/带额外后缀一律不认,
单测同时钉死「第三方任务(Adobe/OneDrive)绝不出现」。
This commit is contained in:
1 parent
c062d1cc8b
commit
cf51e0415a
2 files changed
+60
-1
No files matched your search
@@ -18,6 +18,26 @@
|
||||
/** nodeagent 自己注册过的计划任务名(含历史遗留)。只增不改。 */
|
||||
export const TASK_WHITELIST = ['nodeagent', 'na-gui', 'nodeagent-console'];
|
||||
|
||||
/**
|
||||
* 自重启任务前缀 —— `system.agent.restart` 每次重启都注册
|
||||
* `nodeagent-selfrestart-<毫秒时间戳>`(动作是「杀旧 PID → 前台拉起新进程」)。
|
||||
*
|
||||
* 2026-10-27 真机发现:这类任务不在上面的白名单里,于是**卸载时漏删**——
|
||||
* 留下的任务会继续尝试拉起已被删除的 agent.mjs,形成每次登录都失败一次的僵尸。
|
||||
* 但它也不能被当成垃圾随手清:**正在 Running 的那一个往往就是当前 agent 的
|
||||
* 父任务**(删除会连带杀掉 agent)。故只把它纳入「卸载清理」的判定集合,
|
||||
* 由调用方在「已经停掉 agent」之后使用。
|
||||
*/
|
||||
export const SELF_RESTART_PREFIX = 'nodeagent-selfrestart-';
|
||||
|
||||
/** `nodeagent-selfrestart-<纯数字>` —— 严格到毫秒时间戳形态,不接受任何通配。 */
|
||||
const SELF_RESTART_RE = /^nodeagent-selfrestart-\d{6,}$/;
|
||||
|
||||
/** 是否是本框架的自重启任务(严格命名空间,非模糊匹配)。 */
|
||||
export function isSelfRestartTask(name) {
|
||||
return typeof name === 'string' && SELF_RESTART_RE.test(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计划删除名单:白名单内**且实际存在**的任务,按白名单固定顺序返回。
|
||||
*
|
||||
@@ -37,5 +57,11 @@ export function planTaskCleanup(existing) {
|
||||
for (const name of TASK_WHITELIST) {
|
||||
if (present.has(name)) out.push(name);
|
||||
}
|
||||
// 自重启任务:仅接受严格命名空间(`nodeagent-selfrestart-<数字>`),
|
||||
// 按名字排序保证输出稳定;与白名单重名时去重(实际不会发生,防御性)。
|
||||
const selfRestart = [...present].filter(isSelfRestartTask).sort();
|
||||
for (const name of selfRestart) {
|
||||
if (!out.includes(name)) out.push(name);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { TASK_WHITELIST, planTaskCleanup } from '../../scripts/lib/scheduled-tasks.mjs';
|
||||
import { TASK_WHITELIST, isSelfRestartTask, planTaskCleanup } from '../../scripts/lib/scheduled-tasks.mjs';
|
||||
|
||||
/**
|
||||
* na-gui 陈旧计划任务清理(ARCH B-P1-6 / T05)。
|
||||
@@ -100,3 +100,36 @@ test('control.cmd 菜单暴露 cleanup 入口(纯 ASCII + CRLF 由 ps1-encodin
|
||||
assert.match(cmd, /call :RUN cleanup/, 'control.cmd 菜单必须有 cleanup 项转发');
|
||||
assert.match(cmd, /8\)\s*Cleanup stale tasks/, 'control.cmd 菜单应展示 cleanup 项');
|
||||
});
|
||||
|
||||
// ===========================================================================
|
||||
// 自重启任务(2026-10-27 真机发现:卸载漏删 → 僵尸任务反复拉起已删文件)
|
||||
// ===========================================================================
|
||||
|
||||
test('isSelfRestartTask:只认严格命名空间 nodeagent-selfrestart-<数字>', () => {
|
||||
assert.equal(isSelfRestartTask('nodeagent-selfrestart-1793077118968'), true);
|
||||
assert.equal(isSelfRestartTask('nodeagent-selfrestart-123456'), true, '6 位时间戳级仍算');
|
||||
// 以下都不是我们注册的名字,绝不能被当成自重启任务
|
||||
assert.equal(isSelfRestartTask('nodeagent-selfrestart-'), false, '没有数字');
|
||||
assert.equal(isSelfRestartTask('nodeagent-selfrestart-abc123'), false, '非纯数字');
|
||||
assert.equal(isSelfRestartTask('nodeagent-selfrestart-123'), false, '位数过短(非时间戳形态)');
|
||||
assert.equal(isSelfRestartTask('mynodeagent-selfrestart-123456'), false, '前缀必须从头匹配');
|
||||
assert.equal(isSelfRestartTask('nodeagent-selfrestart-123456-extra'), false, '不得带额外后缀');
|
||||
assert.equal(isSelfRestartTask(''), false);
|
||||
assert.equal(isSelfRestartTask(null), false);
|
||||
});
|
||||
|
||||
test('planTaskCleanup:白名单外的自重启任务纳入清理,且仍然只增不误删', () => {
|
||||
const plan = planTaskCleanup([
|
||||
'nodeagent',
|
||||
'nodeagent-selfrestart-1793077118968',
|
||||
'nodeagent-selfrestart-1793077118999',
|
||||
'Adobe Acrobat Update Task', // 用户/第三方任务,绝不能碰
|
||||
'OneDrive Standalone Update',
|
||||
'nodeagent-selfrestart-notatask',
|
||||
]);
|
||||
assert.deepEqual(plan, [
|
||||
'nodeagent',
|
||||
'nodeagent-selfrestart-1793077118968',
|
||||
'nodeagent-selfrestart-1793077118999',
|
||||
], '白名单先出、自重启按名字排序,第三方任务一律不出现');
|
||||
});
|
||||
Reference in new issue
Block a user