Agent任务超时处理,长时间运行任务心跳与超时终止
Agent 长时间运行任务最怕的不只是慢,而是悄悄卡死却不退出。
一旦任务失去响应,又没有超时终止机制,后续流程会一直等待,甚至堆积大量僵尸进程。
本文会从心跳机制和超时终止两个角度,给出一个零基础也能照做的方案,最后带你自己验证效果。
先理解心跳与超时终止的关系
心跳是 Agent 定时发给调度端的状态信号,证明任务还活着。
调度端收到心跳后,记录最后一次时间;
如果超过设定阈值仍未收到,就判定任务超时并主动终止。
心跳间隔和超时阈值要分开设置,通常超时阈值是心跳间隔的 3 到 5 倍,避免网络抖动误杀。
注意:心跳只能用来发现任务异常,真正回收资源还需要执行终止动作。
所以完整的超时处理必须包含两个部分:心跳检测和终止指令。
准备条件与适用场景
这套方案适用于 Linux 环境下的 Agent 进程,比如通过 systemd 托管的定时任务、Shell 脚本或 Python 脚本。
你只需要:
- 能修改 Agent 启动配置的权限
- 知道 Agent 当前运行的 PID 或服务名
- 有查看日志的途径(journalctl 或日志文件)
如果你正在开发自己的 Agent,请确保心跳逻辑独立于任务主流程,否则主流程卡死时心跳也会跟着停,无法区分是网络问题还是任务问题。
配置超时终止的三种常用方式
方式一:使用 timeout 命令直接限制运行时长
Shell 或命令行启动时,直接用 timeout 包裹原命令,到达指定秒数后强制发送终止信号。
timeout 300 /opt/agent/run_task.sh
如果想让超时更“暴力”,可以加 -s KILL 发送 KILL 信号,但建议先尝试 TERM。
timeout -s TERM 300 /opt/agent/run_task.sh
方式二:通过 systemd 管理 Agent 服务超时
如果 Agent 以 systemd 服务运行,在 service 文件里设置 TimeoutStopSec 和 RuntimeMaxSec。
[Service]
ExecStart=/opt/agent/run_task.sh
RuntimeMaxSec=300
TimeoutStopSec=30
Restart=on-failure
RuntimeMaxSec=300表示服务最多运行 300 秒,超时直接停止并进入失败状态。TimeoutStopSec=30表示停止时最多等 30 秒,超时后强制 KILL。
改完配置后执行 systemctl daemon-reload,再重启服务。
方式三:自己写心跳脚本 + crontab 强杀
这种方式适合没有 systemd 的老环境。
用 crontab 每分钟检查 Agent 的最后心跳时间,超时就杀掉进程。
#!/bin/bash
HEARTBEAT_FILE=/var/run/agent_heartbeat
TIMEOUT=300
if [ -f "$HEARTBEAT_FILE" ]; then
LAST=$(stat -c %Y "$HEARTBEAT_FILE")
NOW=$(date +%s)
DIFF=$((NOW - LAST))
if [ $DIFF -gt $TIMEOUT ]; then
pkill -f agent_run_task
echo "Agent timeout, killed at $(date)" >> /var/log/agent_timeout.log
fi
fi
将脚本放进 crontab 每分钟执行一次:
- * * * * /opt/scripts/check_agent_heartbeat.sh
Agent 自己的心跳更新只需在任务循环里定期执行 touch /var/run/agent_heartbeat。
避坑指南:为什么超时后进程还在
以下三个坑最容易导致超时失效,强烈建议提前规避。
- 只杀主进程,不杀子进程。很多任务会拉起子进程,超时杀主进程后子进程变成孤儿继续运行。方案是使用
pkill按完整命令匹配,或使用kill -- -PGID杀进程组;systemd 默认会清理 cgroup 下所有进程,算是更省心的选择。 - 心跳文件被误更新。如果心跳文件路径写错或权限不对,导致 Agent 没权限更新,就会频繁误杀。记得检查日志中的刷时间记录。
- 超时阈值设得太小。长任务偶发 GC 暂停或网络抖动,阈值太小容易误杀。建议先用日志统计一次正常任务的最长耗时,再乘以 1.5 作为阈值。
如何验证超时真正生效
不要等到线上出事再验证。
你可以在测试环境模拟一个卡死的任务。
sleep 600
假设模拟任务最长允许 60 秒,执行后观察是否在第 60 秒左右被终止。
- 使用 systemd 时,执行
systemctl status 服务名,看 Active 状态和退出码。 - 使用 timeout 命令时,超时后进程会退出,通过
echo $?查看退出码为 124。 - 使用心跳脚本时,查看
/var/log/agent_timeout.log是否生成了新的记录。
验证时建议同时监控 CPU 和内存占用,确认进程被彻底回收。
如果发现进程残留,优先检查子进程和进程组处理方式。
如果你正在配置 Agent 任务超时处理,建议先用最小复现环境试一遍本文的三种方法,再选择最适合自己业务的一种。
正式上线后定期观察心跳日志和超时记录,才能让长时间运行任务始终保持可控。