AI多Agent协作系统实战(五十二):我删了定时器,进程还在偷偷干活

系列第52篇 | 计划任务删了,8小时常驻进程却还在每10分钟"交作业"------双定时源的隐藏重复

背景

"定时报告又在重复了,你去查一下。"

用户一句话,我又回到了熟悉的排查现场。我们的AI数字员工系统里,62号Windows机器(测试服务器)每隔几分钟就往飞书推一条统筹报告。上一轮明明已经加了去重------报告内容不变就静默,怎么又冒出来了?

我登上服务器,先看cron的执行记录。

问题1:报告"固定"在了14:39

cron日志显示得清清楚楚:

makefile 复制代码
14:36:04  159B   ← 静默
14:39:17  771B   ← 发送了
14:42:04  159B   ← 静默
14:45:04  159B   ← 静默
14:48:04  159B   ← 静默
14:51:04  159B   ← 静默

定时任务每3分钟跑一次,状态正常,可只有14:39发了一条,之后再也没发。用户看到的现象是:报告"固定"在14:39,不更新了。

等等------用户上一轮抱怨的是"重复发",这一轮抱怨的好像是"不发了"?其实两个是同一个问题的两面:该静默的时候不静默,该更新的时候不更新

去重逻辑是这样的:把报告文本做hash,和上一次的hash对比,相同就静默。但问题是------报告标题里带着时间戳

复制代码
【统筹报告 08-27 14:39】

每3分钟跑一次,标题里的分钟数就变一次(14:39→14:42→14:45),hash跟着变,去重永远失效------于是每3分钟发一条一模一样的报告。用户被刷屏,我加上"hash排除标题行"的修复,只对正文做hash------正文没变就静默。14:39之后不再发,正是修复生效的表现

第一层问题解决了。但我总觉得哪里不对------报告是消停了,可这服务器上的"定时器",好像不止一个?

问题2:进程列表里有个"幽灵"

我习惯性地看了眼进程列表,一个PID扎眼了:

scss 复制代码
PID 4904 (09:16:40)  python.exe D:\ai-team-collab\app\scripts\task_monitor_loop.py

**09:16启动,到现在跑了8个多小时。**这是一个常驻进程。可我记得------昨晚我们判断loop已经冗余(cron已经全覆盖超时/派发/唤醒),把它的计划任务 ai_loop 删掉了啊。

删了计划任务,进程怎么还在?

我把这个发现跟用户汇报,用户的反应很平静:"处理。"------但我心里清楚,这玩意儿不查明白,类似的"幽灵"以后还会冒出来。

问题3:删了定时器,为什么进程还在?

扒开启动链路,真相很简单,也很有代表性。

我们的Windows机器上,服务有两条完全独立的启动通道

通道A:计划任务(schtasks)

复制代码
ai_loop  →  每10分钟 → python task_monitor_loop.py

计划任务的特点是每次到点拉一个新进程,跑完就退

通道B:启动脚本(start_services.ps1)

powershell 复制代码
Start-Process -WindowStyle Hidden -FilePath $rtPy -ArgumentList $loopSrv ...

启动脚本的特点是开机拉起一个常驻进程,进程自己while True循环

loop.py长这样:

python 复制代码
while True:
    time.sleep(120)
    _ensure_ws_server()
    subprocess.run([py, tm], timeout=300)   # 跑完整心跳
    time.sleep(600)

我们删的是通道A(计划任务),通道B(常驻进程)压根没动过。

一个进程,两个"爸爸":计划任务和启动脚本都能把它拉起来。你以为删了定时器它就死了?不,它是启动脚本的孩子,09:16开机时就被生下来了,之后自己while True循环,跟计划任务一点关系都没有

这就好比:你以为把闹钟电池抠了,结果发现房间里还蹲着一个机器人,每10分钟自动干一次活------它俩根本不是一个东西。

问题4:这个"幽灵"到底干了什么坏事?

loop每10分钟跑一次 task_monitor.py 的完整心跳------包含发报告:

bash 复制代码
cron(*/3):  task_monitor_report_cron.py  →  报告(有hash去重)✅
loop(10分钟):task_monitor.py 完整main     →  报告(无hash去重)⚠️

任务空闲的时候,loop的main会发现"空闲暂停",安静闭嘴------所以平时看不出问题。但只要有任务在跑 ,loop每10分钟发一条完整报告,cron每3分钟发一条去重报告------两个定时源,各发各的,用户看到的就是"重复发"。

而且更阴险的是:start_services.ps1每次开机都会再拉起一个loop(我们之前还给它写了幂等检查------"已在运行就跳过"------这反而让那个09:16的老进程一直"合法"地活着)。删计划任务、改配置,都碰不到这个已经run了8小时的老进程。

修复:杀进程 + 断根

两步走:

bash 复制代码
# 第一步:干掉幽灵(立竿见影)
taskkill /PID 4904 /F
# 输出: 成功: 已终止 PID 4904 的进程

# 第二步:断根(防止开机再拉起)
# start_services.ps1 删掉第5段(task_monitor loop),只留4个服务:
# Hermes / OpenClaw / Web UI / WS gateway

改完验证:

sql 复制代码
[skip] Hermes already running
[skip] OpenClaw already running
[skip] Web UI already running
[skip] WS gateway already running

4个服务,全部幂等跳过,没有loop了。之后update包同步,61号Linux机也确认无loop进程(Linux压根没人拉它------loop文件在但从不执行)。

经验总结

  1. 删计划任务 ≠ 停进程 。计划任务是"每次到点拉起",常驻进程是"开机拉一次自己循环"------两条启动通道互不相干,删一个另一个还活着。排查"定时器还在跑"先 tasklist / ps aux 看有没有常驻进程,别只查计划任务表。

  2. 双定时源 = 定时炸弹 。同一个动作(发报告)挂了两个定时器,平时一个静默一个活跃,看着没事;一旦条件变化(任务活跃),两个一起发声,用户看到的就是"重复"。一个动作只允许一个定时源,加第二个之前先问:旧的删干净了吗?

  3. "删了还在跑"的进程,是隐藏的重复源 。8小时常驻进程比计划任务难发现得多------它不报错、不刷屏、安安静静每10分钟干一次活。定期 tasklist | findstr python 对照启动脚本,看有没有"计划外"的常驻进程。

  4. 幂等检查会掩盖残留 。"已在运行就跳过"是好的防御,但也让老的残留进程永远合法------杀进程要连根(停进程+改启动脚本),不然它换个身份继续活。

定时器删了,进程还在偷偷干活------你以为关掉的,可能只是开关,不是电源。

相关推荐
星火102417 分钟前
【从 0 到 1 动手造 Agent】02、确定性铁笼 LangGraph
人工智能·后端·agent
唐青枫19 分钟前
别把 Debug 和 Release 混为一谈:Zig Build Mode 全面解析
后端
A_nanda20 分钟前
拆解ASP.NET Core 底层源码!从零手写
后端·asp.net
钱栈up22 分钟前
别忽略INFO日志:我用AI编码助手1小时修完3个接口的隐藏Bug
后端·json·trae
星火102423 分钟前
【从 0 到 1 动手造 Agent】03、给 Agent 装上操作系统——MemGPT/Letta 内存分层与自我演化
人工智能·后端·agent
万物智能24 分钟前
OpenHarmony源码树解剖—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
前端·后端
深入云栈25 分钟前
一文搞懂Netty 4.2六大核心概念:Channel/EventLoop/Selector/ByteBuf 如何关联
java·后端
MetaLite31 分钟前
SpringBoot接口通用返回对象Resp设计
java·spring boot·后端
姚杨31 分钟前
聊了三年 DDD,代码里全是贫血模型:老陈一句话点破,落地先过这几关
后端·orm