为什么 gateway.run 总是自动重启?从一条 Hermes 日志看懂进程替换、CPU 占用与排查思路
很多人在运行 Hermes 类 Agent 或 Gateway 服务时,会遇到一个看起来很困惑的问题:
“
明明只启动了一次程序,为什么日志总在提示重启?
为什么 CPU 突然飙高?
gateway run --replace到底做了什么?
本文基于一段真实日志输出,拆解问题发生的原因,并提供一套可以直接操作的排查路径。全文只基于已有对话内容展开,不额外引入外部信息。
问题是怎么出现的?
先看日志:
WARNING gateway.run: Shutdown diagnostic — other hermes processes running:
dapen 1570 92.6 2.0 94260 83524 ? Ss 20:12 0:01 /home/dapen/.hermes/hermes-agent/venv/bin/python -m hermes_cli.main gateway run --replace
不少人看到这里,第一反应是:
“
程序是不是崩了,所以一直自动重启?
但实际情况往往并不是这样。
从这段日志来看,更准确的描述是:
“
系统检测到已经存在另一个 Hermes Gateway 进程,于是触发了替换机制。
换句话说,问题的关键通常不是“自动重启”,而是:
“
多个 Hermes 进程之间发生了相互替换,或者守护程序在重复拉起进程。
先理解日志里到底发生了什么
先拆解这一行:
python -m hermes_cli.main gateway run --replace
这里最关键的是:
gateway run --replace
它说明:
-
Gateway 被启动了; -
启动时发现已有 Hermes 进程存在; -
新进程尝试替换旧进程; -
旧进程退出; -
某些机制又重新拉起旧进程; -
最终进入循环。
所以问题的核心不是:
“
“为什么会重启?”
而是:
“
“为什么会不断出现新旧进程互相替换?”
从日志看出什么异常?
先看完整的一段:
dapen 1570 92.6 2.0 94260 83524 ? Ss 20:12 0:01
这是一个典型的 ps aux 风格输出。
字段顺序固定:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
对应关系如下:
很多人会问:
“
你怎么知道 CPU 是 92.6%?
因为:
92.6
对应的是:
%CPU
字段。
所以,这个进程已经占用了约 92.6% 的 CPU。
为什么高 CPU 值值得警惕?
再看两个字段:
START 20:12
TIME 0:01
意味着:
- ◉
进程刚启动; - ◉
累计运行时间很短; - ◉
但 CPU 占用非常高。
这种现象通常意味着:
情况一:快速重启循环
进程不断:
启动 → 退出 → 启动 → 退出
于是系统持续消耗资源。
情况二:忙循环(Busy Loop)
程序没有真正工作,而是在不停检测:
是否已有进程?
是否替换?
是否退出?
形成一个高频循环。
情况三:Watchdog 拉起循环
外部监控程序不断:
发现进程退出
↓
重新拉起
↓
再次退出
↓
继续拉起
这种情况 CPU 通常也会迅速上升。
为什么会一直自动重启?
下面是几个最常见原因。
原因一:systemd 或守护程序反复拉起
这是最容易忽略的问题。
很多人以为:
“
我只是手动运行了一个命令。
但实际上系统可能已经在后台运行了一个守护服务。
例如:
- ◉
systemd - ◉
supervisord - ◉
pm2 - ◉
Docker restart policy - ◉
shell 循环脚本
这些工具会自动监控进程。
一旦发现退出:
退出
↓
重新启动
如果你的 Hermes 又用了:
gateway run --replace
事情就会变成:
新进程启动
↓
发现旧进程
↓
replace 杀掉旧进程
↓
systemd 发现旧进程被杀
↓
再次启动旧进程
↓
形成循环
最终表现为:
“
“怎么一直重启?”
如何检查是不是 systemd 导致?
执行:
systemctl --user status hermes
或者:
systemctl status hermes
如果看到相关服务在运行,就说明可能存在自动拉起机制。
还可以查看:
ps aux | grep hermes
确认是否有多个相关进程。
特别注意 Restart=always
如果配置里存在:
Restart=always
说明:
“
进程退出后一定会重新启动。
这种情况下,与 --replace 搭配,很容易出现无限替换。
原因二:你其实启动了多个 Gateway
很多人无意中做过这样的事情:
第一次启动:
gateway run
后来忘了,又开一个终端:
gateway run --replace
于是:
第一个进程在运行。
第二个进程启动时:
发现已有 Hermes
↓
执行 replace
↓
替换旧实例
然后旧实例可能又被外部机制拉起。
最终:
“
多个 Gateway 相互抢占。
如何确认是不是多实例?
执行:
pgrep -af hermes
如果看到多个:
gateway run
gateway run --replace
那基本可以确认:
“
是多实例问题。
原因三:PID 文件或 Socket 没清理
很多 CLI 工具会创建:
- ◉
pid 文件 - ◉
lock 文件 - ◉
socket 文件
用于记录:
“
当前已有运行实例。
但如果程序异常退出:
这些文件可能残留。
于是 Hermes 会误以为:
“
“已经有进程在运行。”
然后不断触发 replace。
如何检查?
查看:
ls -la ~/.hermes
重点关注:
.pid
.lock
gateway.sock
之类文件。
如果确认没有实际运行进程,可以尝试清理。
如何清理?
先结束 Hermes:
pkill -f hermes
然后:
rm -rf ~/.hermes/tmp/*
rm -rf ~/.hermes/*.lock
最后重新启动。
原因四:Docker 自动重启
如果 Hermes 跑在容器里,也可能出现类似问题。
例如容器配置:
"RestartPolicy": {
"Name": "always"
}
逻辑会变成:
replace 杀进程
↓
container exit
↓
Docker 自动拉起
↓
重复
表现出来就是:
“
“怎么一直自动重启?”
原因五:内部 Watchdog 导致循环
还有一种情况:
Hermes 本身带有监控机制。
可能存在:
父进程
↓
监控子进程
↓
子进程 replace 父进程
↓
父进程再次拉起
形成“双 watchdog”。
这类问题常见特征是:
进程树异常复杂。
如何检查进程树?
执行:
pstree -ap | grep hermes
如果看到类似:
hermes-agent
└─python
└─python -m hermes_cli.main gateway run --replace
甚至多层嵌套:
python
└─python
└─python
说明:
“
可能出现了内部监控循环。
为什么日志里 CPU 会这么高?
很多用户会注意到:
92.6% CPU
并怀疑:
“
是不是程序本身有 bug?
其实未必。
因为:
START 20:12
TIME 0:01
意味着:
“
进程启动很短时间,但 CPU 已经被大量消耗。
这通常是:
1. Restart Loop
不断启动:
启动 → 退出 → 启动
2. Fork Loop
不断创建新进程。
3. Watchdog Loop
监控程序互相拉起。
放任不管会怎样?
如果进入循环:
可能出现:
日志暴涨
日志不断输出:
other hermes processes running
文件句柄耗尽
频繁创建连接。
Socket 被占用
新进程无法绑定。
CPU 长时间高占用
机器明显变卡。
内存逐渐上涨
尤其是子进程没有及时回收时。
推荐的排查顺序
如果你遇到:
“
Hermes 总自动重启
建议按下面顺序检查。
第一步:看是否有多个进程
执行:
pgrep -af hermes
看是否出现多个实例。
重点观察:
gateway run
gateway run --replace
是否同时存在。
第二步:查看进程树
执行:
pstree -ap | grep hermes
确认:
- ◉
是否多层 Python; - ◉
是否 watchdog 循环; - ◉
是否嵌套启动。
第三步:检查 systemd
执行:
systemctl --user | grep hermes
查看:
“
是否存在后台服务。
第四步:查看 .hermes 目录
执行:
ls -la ~/.hermes
检查:
- ◉
pid - ◉
lock - ◉
socket
是否异常残留。
一个最直接的解决方案
如果暂时不确定原因,可以先做一次“彻底清理”。
先结束所有 Hermes:
pkill -9 -f hermes
确认进程已经消失:
pgrep -af hermes
如果没有输出:
说明已清理完成。
然后只启动一次:
gateway run
注意:
“
先不要加
--replace。
如果这样运行稳定:
说明问题大概率是:
“
多实例互相抢占。
一个容易忽略的误区
很多人会误以为:
“
--replace是“更稳定”的启动方式。
但从日志行为来看:
它的作用更接近:
“
替换已有实例。
因此:
如果你已经确定没有旧实例:
直接:
gateway run
通常更容易排查问题。
而:
gateway run --replace
适合:
“
明确知道已有实例存在时使用。
否则容易让问题变复杂。
FAQ:关于 Hermes 自动重启的常见问题
为什么只启动一次,却一直提示重启?
因为:
“
很可能后台已经有 Hermes。
新实例检测到已有进程后,开始 replace。
于是看起来像“无限重启”。
为什么 CPU 会到 92.6%?
因为:
92.6
是 ps aux 的 %CPU 字段。
结合:
START 20:12
TIME 0:01
说明:
“
短时间内 CPU 被大量占用。
常见原因是:
- ◉
重启循环; - ◉
watchdog 循环; - ◉
多实例互抢。
gateway run --replace 会干什么?
作用是:
“
检测已有实例,并替换它。
不是简单启动。
如何确认是不是多个实例?
执行:
pgrep -af hermes
查看是否出现:
gateway run
gateway run --replace
多个进程。
如何实时看 CPU 占用?
可以执行:
top -p 1570
或:
htop
查看实时资源占用。
最简单的恢复方式是什么?
通常是:
先全部结束:
pkill -9 -f hermes
确认:
pgrep -af hermes
没有输出。
再只启动一次:
gateway run
并暂时不要使用:
--replace
观察是否稳定。
HowTo:快速排查 Hermes 自动重启
步骤 1:确认是否多实例
pgrep -af hermes
步骤 2:查看进程树
pstree -ap | grep hermes
步骤 3:检查后台服务
systemctl --user | grep hermes
步骤 4:检查 Hermes 文件
ls -la ~/.hermes
步骤 5:彻底清理
pkill -9 -f hermes
确认:
pgrep -af hermes
无输出。
步骤 6:只启动一次
gateway run
不要先用:
gateway run --replace

