历史版本在被控端上注册过 na-gui 等旧名计划任务,漏删会留下「端口被占、 新版本起不来」的幽灵任务。误删用户自己的任务则是比漏删严重得多的 生产事故 —— 故只按白名单删。 - scripts/lib/scheduled-tasks.mjs(新):TASK_WHITELIST(nodeagent / na-gui / nodeagent-console,只增不改)+ planTaskCleanup 纯函数 (查询结果注入,白名单外一律不删、精确匹配大小写敏感、重复名去重)。 - scripts/uninstall.ps1:卸载末尾按白名单逐个注销(-ccontains 存在性 检查 + 动作进日志)。 - scripts/control.ps1:新增 cleanup 子命令(ValidateSet + Clear-StaleTasks), Uninstall-Agent 复用同一白名单;control.cmd 菜单加第 8 项 (CRLF 安全插入,纯 ASCII 不变)。 - tests/unit/na-gui-cleanup.test.mjs(新,10 例):白名单命中才删 / 白名单外零动作 / 空列表 / 重复名 / 脏输入 + ps1 源码守卫与跨端 一致性守卫(白名单 mjs 与 ps1 漂移即红 —— 注入故障实测 2 处变红, 恢复后全绿)。
42 lines
1.9 KiB
JavaScript
42 lines
1.9 KiB
JavaScript
/**
|
|
* Windows 计划任务清理白名单(B-P1-6 / T05)。
|
|
*
|
|
* ## 为什么需要
|
|
* nodeagent 历史版本/缺陷修复在被控端上注册过计划任务(na-gui 等旧名),
|
|
* 卸载时若漏删,会留下「端口被占、起不来新版本」的幽灵任务。
|
|
* 但清理动作**只许按白名单删**——误删用户自己的任务是比漏删严重得多的
|
|
* 生产事故(可能停掉业务服务),故本文件是纯函数 + 白名单,禁通配删除。
|
|
*
|
|
* ## 铁律
|
|
* - 零依赖、零 import:与 startup-guard-core 同风格,任何 Node ≥22 可加载;
|
|
* - 白名单**只增不改**:发现新的历史任务名时追加,不从清单里移除旧名
|
|
* (老被控端上旧名任务可能还在);
|
|
* - 匹配是精确相等(大小写敏感):Windows 任务名实际大小写不敏感,
|
|
* 但这里宁可漏删也不模糊匹配——模糊匹配是误删之门。
|
|
*/
|
|
|
|
/** nodeagent 自己注册过的计划任务名(含历史遗留)。只增不改。 */
|
|
export const TASK_WHITELIST = ['nodeagent', 'na-gui', 'nodeagent-console'];
|
|
|
|
/**
|
|
* 计划删除名单:白名单内**且实际存在**的任务,按白名单固定顺序返回。
|
|
*
|
|
* 纯函数:查询结果由调用方注入(PowerShell 侧 Get-ScheduledTask),
|
|
* 本函数不碰文件系统、不碰注册表 —— 判断可单测,误删风险可证明。
|
|
*
|
|
* @param {string[]} existing 被控端上实际存在的任务名(可含重复/空串/非字符串)
|
|
* @returns {string[]} 需要删除的任务名(每个最多一次;白名单外一律不出现)
|
|
*/
|
|
export function planTaskCleanup(existing) {
|
|
if (!Array.isArray(existing)) return [];
|
|
const present = new Set();
|
|
for (const n of existing) {
|
|
if (typeof n === 'string' && n.length > 0) present.add(n);
|
|
}
|
|
const out = [];
|
|
for (const name of TASK_WHITELIST) {
|
|
if (present.has(name)) out.push(name);
|
|
}
|
|
return out;
|
|
}
|