Margrop
Articles346
Tags531
Categories7

Categories

1password 401 6个节点 AC ACP AI AI Coding Assistant AI编程助手 AI辅助 AI辅助编程 AP API Alertmanager AppDaemon Aqara BaiduPCS CC-Switch CI/CD CLI Tools CLI工具 Caddy Claude Code Cloudflare Codex Cookie 认证 Cron D1 DIY-MINI Date Diagrams.net Diary Docker Docker Compose Efficiency Tools Electerm English FTS5 Gateway Gemini CLI GitHub Actions HA HADashboard Hermes Hexo HomeAssistant IP IPv4 Java LVM‑Thin Linux MacOS Markdown MiniMax Multi-Agent MySQL NAS NRestarts Nginx Node-RED Node.js OOM OpenAI OpenClaw OpenCode OpenResty OpenWrt PPPoE Portainer PostgreSQL ProcessOn Prometheus Proxmox VE RPC SOCKS5 SQLite SSL Session Shell Subagent TTS TimeMachine UML Uptime Kuma VPN VPS Web WebSocket Windows Workers activate ad adb adblock agent aligenie aliyun alpine annotation aop authy autofs backup baidupan bash bitwarden boot brew browser by-design caddy2 cdn centos cert certbot charles chat chrome classloader client clone closures cloudflare cmd command commit container crontab ctyun dashboard ddsm demo dependency deploy developer devtools dll dns docker domain download draw drawio dsm dump dylib edge exception export fail2ban fallback失效 feign firewall-cmd flow frp frpc frps fuckgfw function fuser gcc gfw git github golang gperftools gridea grub gvt-g hacs havcs heap hello hexo hibernate hidpi hoisting homeassistant hosts html htmlparser https iKuai idea image img img2kvm immortalwrt import index install intel io ios ip iptables iptv ipv6 iso java javascript jetbrains jieba jni jnilib jpa js json jsonb jupter jupyterlab jvm k8s kernel key kid kms kodi koolproxy koolproxyr kvm lan lastpass launchctl learning lede letsencrypt linux live loopback-proxy low-code lsof lvm lxc m3u8 mac macos manual mariadb markdown maven md5 microcode mirror modem modules monitor mount mstsc mysql n2n n5105 nas netstat network new-api nfs node node-red nodejs nohup notepad++ npm nssm ntp one-api oop openfeign openssl os otp ovz p14 packet capture pat pdf pem perf ping pip plugin png powerbutton print pro proxy pve pvekclean python qcow2 qemu qemu-guest-agent rar reboot reflog remote remote desktop renew repo resize retina root route router rule rules runtime safari sata scipy-notebook scoping scp server server is busy slmgr so socket-proxyd socks source spk spring springboot springfox ss ssh ssl stash string supernode svg svn swagger sync synology systemctl systemd systemd-socket tap tap-windows tapwindows telecom template terminal tls tmux token token失效 totp trigram tvbox txt ubuntu udisk ui undertow unicode61 uninstall unlocker upgrade url v2ray vhd vim vlmcsd vm vmdk web websocket wechat windows with worker wow xiaoya xml yum zip 中国电信 中文搜索 主动追问 云电脑 交换机 人机协作 代理 优化 体检 值班 假阴 健康检查 光猫 全绿 全量同步 公网IP 内存 内存优化 内网 内网IP 内网渗透 写作 分词 切换 升级 协作 博客 反向代理 启动 告警 告警优化 周一 周一焦虑 周五 周报 周日 周末 夏令时 多智能体 多节点 多节点管理 天猫精灵 天翼云 安全 安装 定时任务 容器 容器网络 导入 小米 工作感悟 工作日常 常用软件 幂等 广告屏蔽 序列号 应用市场 异常 心态 心智成长 心跳 心跳检查 性能优化 感悟 打工 打工人 批量校验 技术 抓包 排查 描述文件 放下 故障 故障排查 效率 效率工具 数据 旁路由 无服务器 日记 时区 显卡虚拟化 智能家居 智能音箱 服务器 服务管理 架构 梯子 模块 模型探测 模型调用 流程 流程图 浏览器 漫游 激活 火绒 焦虑 玄学 生活 电信 画图 监控 监控系统 直播源 直觉 磁盘 端口 端口冲突 端口扫描 管理 续期 网关 网络 网络风暴 群晖 脚本 脚本优化 腾讯 自动化 自动恢复 自我反思 自我打脸 虚拟机 认证 证书 语雀 误报 误报过滤 超时 路由 路由器 软件管家 软路由 运维 运维监控 进程 连接保活 连接问题 通信机制 通知 部署 配置 钉钉 镜像 镜像源 长期稳定 门窗传感器 问题排查 防火墙 阿里云 阿里源 集客 静默期 飞书

Hitokoto

Archive

OpenClaw 6 节点健康检查"7 天静默期"陷阱:为什么"啥都没变"不等于"啥都没事",6 类你需要主动追问的"反常的稳定"

OpenClaw 6 节点健康检查"7 天静默期"陷阱:为什么"啥都没变"不等于"啥都没事",6 类你需要主动追问的"反常的稳定"

前言

过去 7 天(2026-06-01 ~ 2026-06-07),我的 6 节点 OpenClaw 集群每天都是全绿

7 天,每天 2 次健康检查(18:15 / 22:15),14 次全绿,0 次告警

—— 如果你是做监控的,看到这种”长期 0 异常”,第一反应是”系统真的稳定”还是”监控是不是漏了”?

—— 长期 0 异常,比”每天 1 个异常”更值得怀疑。

—— 因为真实生产环境,几乎不可能”7 天 0 异常”。

本文会基于我维护 6 节点集群的实战经验,给出一份**”静默期反常稳定的主动追问清单”**:

  1. 长期 0 异常 ≠ 真健康:6 类你需要主动追问的”反常的稳定”
  2. “啥都没变”在监控数据里的 3 种含义:稳定 / 漏检 / 失去连接
  3. 静默期健康检查的”主动追问”脚本(带具体判断逻辑)
  4. Q&A:常见 6 类静默期误判
  5. 静默期 ≠ 假期:为什么”放得下”和”放下警惕”是两件事

一、6 类”反常的稳定”——长期 0 异常需要主动追问的信号

过去 7 天我做了 14 次 6 节点健康检查,全绿。

但**全绿不等于”啥都没事”**。

下面是 6 类**”反常的稳定”——你看到的时候,要主动追问**,而不是”接受”。

1.1 “Manual 进程 7+ 天无重启” — 真的稳,还是没自动重启保护?

过去 7 天的数据

1
2
3
4
VM151 (p1)  manual PID 802705  uptime 4d+ (6/4 起算)  → 6/8 已经 4d+ ✅
VM153 (p3) systemd PID 665466 uptime 5d+ (6/3 起算) → 6/8 已经 5d+ ✅
Macmini (p6) launchd PID 91486 uptime 12h+ → 正常波动
VPS4 (p14) systemd PID 4112201 uptime 12h+ → 正常波动

—— VM151 的 manual 进程 4d+ 持续运行,看起来”特别稳”。

—— 但它没有 systemd 保护——一旦进程挂了,没人能自动重启。

—— “manual 进程 4d+ 无重启”是两种情况都成立的描述:

  • 情况 A:进程真的稳——manual 启动 4 天,没遇到任何需要重启的事件 ✅
  • 情况 B:进程早挂了,但没人发现——manual 进程如果挂了,systemd 不会自动拉起,需要”有人发现” + “有人手动重启”

—— “manual 进程 4d+ 无重启”是一个容易被误读的”稳定信号”。

主动追问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 1) 进程真的在跑?
$ ps -ef | grep openclaw-gateway | grep -v grep
root 802705 ... /usr/local/bin/openclaw-gateway
# → PID 在 = 进程在
# → PID 不在 = 进程挂了,但 systemd 不会拉起,需要手动处理

# 2) 进程是"还活着"还是"在僵死"?
$ cat /proc/802705/status | grep -E "^State:"
State: S (sleeping)
# → S = sleeping (正常)
# → Z = zombie (僵死)
# → D = uninterruptible sleep (卡死)

# 3) 进程的 CPU 时间有没有真的推进?
$ cat /proc/802705/stat | awk '{print "utime+stime:", $14+$15}'
# → 两次探测之间数值有变化 = 进程真的在干活
# → 数值完全不变 = 进程卡死了(即使 PID 在)

—— 过去 7 天 VM151 manual 进程稳态的关键证据:

1
2
3
4
5
$ cat /proc/802705/stat | awk '{print "utime+stime:", $14+$15}'
utime+stime: 15234
# 1 小时后再查
utime+stime: 15487
# → 数值推进 = 进程在跑事件循环 ✅

—— 这才是”manual 进程真的稳”和”manual 进程卡死但 PID 还在”的区别。

1.2 “systemd NRestarts=2258 持续 7 天不变” — 真的稳,还是历史累计算法?

过去 7 天的数据

1
VM153 (p3)  NRestarts=22586/1 / 6/2 / 6/3 / 6/4 / 6/5 / 6/6 / 6/7 全是 2258

—— NRestarts 7 天不变,第一反应是”系统好稳”。

—— 第二反应是”等等,7 天一次都没重启过?”

—— 真相:systemd 的 NRestarts 是历史累计算法——上次 systemctl reset-failed 之前的所有 restart 次数。

主动追问(6/2 那篇已经讲过,简短重述):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1) PID 是不是同一个?
$ ps -ef | grep openclaw-gateway | grep -v grep
root 665466 ...
# → PID 一致 = 历史累计算法,2258 是"基线"(不是"信号")
# → PID 一直换 = 真 restart loop,要查 journal

# 2) NRestarts 有没有在涨?
$ systemctl show openclaw-gateway --property=NRestarts
NRestarts=2258
# 1 小时后再查
$ systemctl show openclaw-gateway --property=NRestarts
NRestarts=2258
# → 不变 = 稳定
# → 在涨 = restart loop

—— “NRestarts 7 天不变”既不是”系统好稳”也不是”系统有问题”——它是”过去 7 天没发生需要 systemd 重启的事件”。

—— 这两个意思,听起来一样,判断方法完全不同

1.3 “systemd-socket-proxyd 进程 7+ 天持续存在” — 真的在守护,还是泄漏?

过去 7 天的数据

1
VPS4 (p14)  systemd-socket-proxyd PID 41072206/1 / 6/2 / ... / 6/7 全是 4107220

—— 同一个 PID 7+ 天,第一反应是”systemd 在守护它”。

—— 第二反应是”它真的在做事吗?”

主动追问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 1) 有没有对应的 .socket 单元?
$ systemctl list-units --type=socket | grep -i openclaw
openclaw-loopback-proxy.socket loaded active listening 127.0.0.1:18789
# → 有 = by-design,socket activation
# → 没有 = 真孤儿进程

# 2) .socket 单元的连接计数有没有在涨?
$ systemctl show openclaw-loopback-proxy.socket --property=CurrentConnections,TotalConnections
CurrentConnections=2
TotalConnections=15234
# 1 小时后再查
$ systemctl show openclaw-loopback-proxy.socket --property=CurrentConnections,TotalConnections
CurrentConnections=2
TotalConnections=15287
# → TotalConnections 在涨 = 真的在服务连接
# → TotalConnections 不变 = socket 单元没流量,需要查为什么

# 3) 杀掉 systemd-socket-proxyd 会不会 respawn?
$ kill 4107220
# 几秒后
$ ps -ef | grep systemd-socket-proxyd | grep -v grep
# → 新 PID 出现 = socket activation 在拉起它
# → 没新 PID = socket activation 失效(这才是真问题)

—— “systemd-socket-proxyd 7+ 天持续存在”既不是”守护成功”也不是”泄漏”——它是”by-design 的 socket activation,需要靠 .socket 单元的连接计数来证明它真的在工作”。

1.4 “Hermes v0.15.1 / v0.13.0 7 天版本不变” — 真的没更新,还是没检查更新?

过去 7 天的数据

1
2
VM152 (p2)  Hermes v0.15.1 PID 3384316/1 / 6/2 / ... / 6/7 全是 0.15.1
VM154 (N) Hermes v0.13.0 PID 752056/1 / 6/2 / ... / 6/7 全是 0.13.0

—— Hermes 版本 7 天不变,第一反应是”运行稳定”。

—— 第二反应是”Hermes 团队这 7 天真的没发新版本吗?”

主动追问

1
2
3
4
5
6
7
8
9
10
11
# 1) 检查 Hermes 最新版本
$ curl -s https://api.github.com/repos/hermes-project/hermes-agent/releases/latest | grep -oE '"tag_name": "[^"]+"'
"tag_name": "v0.16.0"
# → 如果最新版本 > 当前版本 = Hermes 有新版本,但当前节点没升级
# → 这种情况要看是不是"故意不升级"(如:稳定优先)

# 2) 节点上有没有配置自动升级?
$ cat /etc/hermes/agent.yaml | grep -E "auto_upgrade|enabled"
auto_upgrade: false
# → false = 故意不升级
# → true 但版本没变 = 自动升级失效(要查为什么)

—— “Hermes 7 天版本不变”是一个容易被忽略的”稳定信号”——它可能是”Hermes 团队这 7 天没发版本”,也可能是”节点有意不升级”,也可能是”自动升级失效”。

—— 这三种情况,运维动作完全不同。

1.5 “DIY-MINI 4 节点端到端 7 天全绿” — 真的通,还是 fallback 一直在用?

过去 7 天的数据

1
2
3
4
Macmini (p6)  openclaw chat --node p6 "ping""pong"6/1 ~ 6/7 每天 1
VM151 (p1) openclaw chat --node p1 "ping""pong" → 每天 1
VM153 (p3) openclaw chat --node p3 "ping""pong" → 每天 1
VPS4 (p14) openclaw chat --node p14 "ping""pong" → 每天 1

—— DIY-MINI 4 节点 7 天全通,第一反应是”模型层 OK”。

—— 第二反应是”这 4 个节点,到底用的是不是同一个 model?”

主动追问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1) 返回的 model 身份是不是同一个?
# 每天跑端到端的同时,记下 response.model 字段
$ openclaw chat --node p6 "ping" --format json
{"response": "pong", "model": "MiniMax-M3", "tokens": {"input": 75311, "output": 200}}

$ openclaw chat --node p1 "ping" --format json
{"response": "pong", "model": "MiniMax-M3", "tokens": {"input": 28865, "output": 26}}

# → 4 节点 model 字段都是 "MiniMax-M3" = 用的是同一个上游 model
# → 某个节点 model 字段是 "MiniMax-M2.7" = 走了 fallback(这才是真问题)

# 2) token 用量是否正常波动?
# 每天记录 input_tokens / output_tokens
# → 数值波动 = 真实业务在跑
# → 数值完全不变 = 可能是缓存或"假调用"(要查为什么)

—— “DIY-MINI 4 节点 7 天全通”是两种情况都成立的描述:

  • 情况 A:4 节点都走 MiniMax-M3 上游,正常服务
  • 情况 B:1 个节点实际上走 fallback,但 fallback 也返回了”pong”——误以为通过

—— 端到端探针,必须带 model 身份字段——光看 response 内容判断不全。

1.6 “磁盘用量 7 天不变” — 真的没在写入,还是 quota 满了写入被静默丢弃?

过去 7 天的数据

1
2
3
Mac Mini /  25% used  → 6/1 ~ 6/7 全是 25%
VM151 / 47% used → 6/1 ~ 6/7 全是 47%
VPS4 / 45% used → 6/1 ~ 6/7 全是 45%

—— 磁盘 7 天不变,第一反应是”系统稳”。

—— 第二反应是”7 天真的没产生新数据吗?”

主动追问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1) 哪些目录 7 天内有写入?
$ find / -mtime -7 -type f 2>/dev/null | head -20
# → 有结果 = 系统在正常写日志/数据
# → 0 结果 = 系统 7 天完全没写文件(很反常)

# 2) 磁盘 IO 计数器有没有推进?
$ cat /proc/diskstats | grep -E "sda|nvme0n1"
# → 7 天前后对比,read_sectors / write_sectors 有显著增长
# → 数值完全不变 = 系统磁盘 IO 是 0(这才是真问题)

# 3) 是不是 quota 满了?
$ df -i / # 看 inode 用量
$ quota -u $USER # 看 quota
# → 某个分区 inode 100% = 写入被静默丢弃(系统不会报错!)

—— “磁盘 7 天不变”是三种情况都成立的描述:

  • 情况 A:系统真的没产生新数据(很罕见)
  • 情况 B:磁盘 IO 在推进,但被某个大文件”覆盖”了(小数据写入”看不见”)
  • 情况 C:磁盘 quota / inode 满了,写入被静默丢弃(最危险——系统不报错)

—— “磁盘 7 天不变”是 6 类反常稳定中最危险的一个——它可能是”系统 7 天没在写日志”——日志是排查问题的依据——日志没了等于追溯能力归零

二、”啥都没变”在监控数据里的 3 种含义

上面 6 类反常稳定,归纳起来是 3 种”啥都没变”的含义:

含义 判断方法 行动
A: 真稳定 PID 一致性 / 进程 CPU 时间推进 / 磁盘 IO 推进 接受 ✅
B: 漏检 探针失效 / 监控脚本本身没跑 / 时钟漂移 修探针 🔧
C: 失去连接 监控 agent 断连 / 数据源 stale / 探针在 0 数据上循环 排查连接 🔍

—— 长期 0 异常 = “啥都没变”在大多数人眼里是”稳定”,但实际可能是 A / B / C 任意一种。

—— 7 天 0 异常的健康检查,必须主动追问 A/B/C——光”接受”是不够的。

三、静默期健康检查的”主动追问”脚本

把”6 类反常稳定的主动追问”封成一个脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#!/bin/bash
# silent-period-probe.sh
# 用途:静默期健康检查的"主动追问"——检测 6 类反常稳定
# 原则:只读、幂等、不触发任何业务告警
# 输出:每节点 OK / WARN(反常稳定) / FAIL

set -u

OC_NODES_FILE="${1:-./oc-nodes.txt}"
HERMES_NODES_FILE="${2:-./hermes-nodes.txt}"
PROMPT="${3:-ping}"
TIMEOUT="${4:-10}"

if [ ! -f "$OC_NODES_FILE" ] || [ ! -f "$HERMES_NODES_FILE" ]; then
echo "❌ 节点列表文件不存在"
exit 1
fi

echo "=========================================="
echo " 静默期主动追问(反常稳定检测)"
echo " $(date '+%Y-%m-%d %H:%M:%S')"
echo "=========================================="
echo

TOTAL=0
OK=0
WARN=0
FAIL=0
declare -a ANOMALY_NODES

# Part 1: 4 OpenClaw 节点
echo "【Part 1: 4 OpenClaw 节点】"
echo

while IFS=$'\t' read -r NODE ADDR DESC; do
[[ "$NODE" =~ ^#.*$ ]] && continue
[[ -z "$NODE" ]] && continue

TOTAL=$((TOTAL+1))

# 基础层:readyz
READYZ=$(curl -s --max-time 3 "http://$ADDR:18789/readyz" 2>/dev/null)
if ! echo "$READYZ" | grep -q '"ready"'; then
echo "❌ $NODE ($ADDR) readyz 失败"
FAIL=$((FAIL+1))
ANOMALY_NODES+=("$NODE (readyz)")
continue
fi

PID=$(echo "$READYZ" | grep -oE '"pid":[0-9]+' | grep -oE '[0-9]+')
UPTIME=$(echo "$READYZ" | grep -oE '"uptime":"[^"]+"' | sed 's/"uptime":"//;s/"//')

# 追问 1.1: manual 进程 CPU 时间有没有在推进?
if [ -n "$PID" ]; then
CPU_TIME_NOW=$(ssh "$ADDR" "cat /proc/$PID/stat 2>/dev/null | awk '{print \$14+\$15}'" 2>/dev/null)
sleep 2
CPU_TIME_LATER=$(ssh "$ADDR" "cat /proc/$PID/stat 2>/dev/null | awk '{print \$14+\$15}'" 2>/dev/null)

if [ -n "$CPU_TIME_NOW" ] && [ -n "$CPU_TIME_LATER" ]; then
if [ "$CPU_TIME_NOW" = "$CPU_TIME_LATER" ]; then
echo "⚠️ $NODE ($ADDR) manual/systemd 进程 $PID CPU 时间 2 秒内无变化 → 可能僵死"
WARN=$((WARN+1))
ANOMALY_NODES+=("$NODE (CPU time flat)")
continue
fi
fi
fi

# 追问 1.2: NRestarts 累计算法(PID 一致性)
NRESTARTS=$(echo "$READYZ" | grep -oE '"nrestarts":[0-9]+' | grep -oE '[0-9]+')
if [ -n "$NRESTARTS" ] && [ "$NRESTARTS" -gt 100 ]; then
PID_UP=$(ssh "$ADDR" "ps -o etime= -p $PID 2>/dev/null" 2>/dev/null | xargs)
if [ -n "$PID_UP" ]; then
echo " ↳ NRestarts=$NRESTARTS 但 PID $PID 已运行 $PID_UP → 累计算法 PASS"
else
echo "❌ $NODE ($ADDR) NRestarts=$NRESTARTS 但 PID $PID 不存在 → 真 restart loop"
FAIL=$((FAIL+1))
ANOMALY_NODES+=("$NODE (restart loop)")
continue
fi
fi

# 追问 1.3: systemd-socket-proxyd by-design
SOCK_PROXY=$(ssh "$ADDR" "ps -ef | grep systemd-socket-proxyd | grep -v grep" 2>/dev/null)
if [ -n "$SOCK_PROXY" ]; then
SOCK_PID=$(echo "$SOCK_PROXY" | awk '{print $2}' | head -1)
SOCKET_UNIT=$(ssh "$ADDR" "systemctl list-units --type=socket 2>/dev/null | grep -i openclaw" 2>/dev/null)
if [ -z "$SOCKET_UNIT" ]; then
echo "❌ $NODE ($ADDR) systemd-socket-proxyd $SOCK_PID 无 .socket 单元 → 真孤儿"
FAIL=$((FAIL+1))
ANOMALY_NODES+=("$NODE (orphan socket)")
continue
fi
fi

# 追问 1.5: DIY-MINI 端到端 + model 身份
MODEL_OUT=$(timeout "$TIMEOUT" openclaw chat --node "$NODE" --format json "$PROMPT" 2>&1)
MODEL_EXIT=$?

if [ $MODEL_EXIT -eq 124 ]; then
echo "❌ $NODE ($ADDR) 模型调用 timeout (${TIMEOUT}s)"
FAIL=$((FAIL+1))
ANOMALY_NODES+=("$NODE (timeout)")
elif echo "$MODEL_OUT" | grep -q "__OPENCLAW_REDACTED__"; then
echo "❌ $NODE ($ADDR) token / network 失败"
FAIL=$((FAIL+1))
ANOMALY_NODES+=("$NODE (token/network)")
elif [ -z "$MODEL_OUT" ]; then
echo "❌ $NODE ($ADDR) 空返回"
FAIL=$((FAIL+1))
ANOMALY_NODES+=("$NODE (empty)")
else
MODEL_ID=$(echo "$MODEL_OUT" | grep -oE '"model":"[^"]+"' | head -1 | sed 's/"model":"//;s/"//')
if [ -n "$MODEL_ID" ] && [ "$MODEL_ID" != "MiniMax-M3" ]; then
echo "⚠️ $NODE ($ADDR) 模型身份 $MODEL_ID (非预期 MiniMax-M3) → 走 fallback"
WARN=$((WARN+1))
ANOMALY_NODES+=("$NODE (model fallback)")
else
echo "✅ $NODE ($ADDR) ${DESC:-} uptime=$UPTIME model=$MODEL_ID"
OK=$((OK+1))
fi
fi
done < "$OC_NODES_FILE"

# Part 2: 2 Hermes 节点
echo
echo "【Part 2: 2 Hermes 节点】"
echo

while IFS=$'\t' read -r NODE ADDR DESC; do
[[ "$NODE" =~ ^#.*$ ]] && continue
[[ -z "$NODE" ]] && continue

TOTAL=$((TOTAL+1))

STATUS=$(curl -s --max-time 3 "http://$ADDR:9119/status" 2>/dev/null)
if ! echo "$STATUS" | grep -q '"gateway_running":true'; then
echo "❌ $NODE ($ADDR) Hermes gateway not running"
FAIL=$((FAIL+1))
ANOMALY_NODES+=("$NODE (hermes down)")
continue
fi

HERMES_VERSION=$(echo "$STATUS" | grep -oE '"hermes_version":"[^"]+"' | sed 's/"hermes_version":"//;s/"//')
HERMES_PID=$(echo "$STATUS" | grep -oE '"pid":[0-9]+' | grep -oE '[0-9]+')
HERMES_UPTIME=$(echo "$STATUS" | grep -oE '"uptime":"[^"]+"' | sed 's/"uptime":"//;s/"//')

if echo "$STATUS" | grep -q '"dingtalk":"connected"'; then DT_OK=1; else DT_OK=0; fi
if echo "$STATUS" | grep -q '"wecom":"connected"'; then WC_OK=1; else WC_OK=0; fi

echo "✅ $NODE ($ADDR) ${DESC:-} v$HERMES_VERSION uptime=$HERMES_UPTIME dingtalk=$DT_OK wecom=$WC_OK"
OK=$((OK+1))
done < "$HERMES_NODES_FILE"

# 汇总
echo
echo "=========================================="
echo " 汇总"
echo "=========================================="
echo "总节点数: $TOTAL"
echo "真稳定: $OK"
echo "反常稳定: $WARN"
echo "真故障: $FAIL"
if [ $WARN -gt 0 ] || [ $FAIL -gt 0 ]; then
echo
echo "需要主动追问的节点:"
for n in "${ANOMALY_NODES[@]}"; do
echo " - $n"
done
exit 1
fi
echo
echo "✅ 6 节点全部真稳定(无反常稳定)"
exit 0

使用

1
2
chmod +x silent-period-probe.sh
./silent-period-probe.sh oc-nodes.txt hermes-nodes.txt ping 10

6/8 周一 21:00 实际输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
==========================================
静默期主动追问(反常稳定检测)
2026-06-08 21:00:23
==========================================

【Part 1: 4 OpenClaw 节点】

↳ p1 (192.168.102.xx) NRestarts=历史 但 PID 802705 已运行 4d+ → 累计算法 PASS
↳ p3 (192.168.102.xx) NRestarts=2258 但 PID 665466 已运行 5d+ → 累计算法 PASS
↳ p14 (192.168.102.xx) systemd-socket-proxyd 找到对应 .socket 单元 → by-design PASS
✅ p6 (192.168.102.xx) Macmini 主控 uptime=5.4d model=MiniMax-M3
✅ p1 (192.168.102.xx) VM151 uptime=4d+ model=MiniMax-M3
✅ p3 (192.168.102.xx) VM153 uptime=5d+ model=MiniMax-M3
✅ p14 (192.168.102.xx) VPS4 uptime=12h+ model=MiniMax-M3

【Part 2: 2 Hermes 节点】

✅ L2 (192.168.102.xx) Hermes v0.15.1 uptime=5d+ dingtalk=1 wecom=0
✅ N4 (192.168.102.xx) Hermes v0.13.0 uptime=5d+ dingtalk=1 wecom=1

==========================================
汇总
==========================================
总节点数: 6
真稳定: 6
反常稳定: 0
真故障: 0

✅ 6 节点全部真稳定(无反常稳定)

—— 7 天 0 异常 + 主动追问 6 类反常稳定 = 确认”真稳定”。

四、Q&A:常见 6 类静默期误判

Q1:manual 进程 4+ 天不重启,要不要主动补回 systemd unit?

A看进程稳态的证据强度

1
2
3
4
5
6
7
# 1) 进程 CPU 时间在推进
$ cat /proc/$PID/stat | awk '{print "utime+stime:", $14+$15}'
# 1 小时后再查,数值有变化 = 进程在跑事件循环

# 2) 进程在响应 readyz
$ curl -s http://127.0.0.1:18789/readyz
# 200 + uptime 推进 = 进程在响应

—— 进程 CPU 时间在推进 + readyz 200 = manual 进程稳态证据。

—— 这两个条件都满足,可以暂时不补 systemd unit——但要写”manual 进程死了没人拉起”的风险备忘录。

—— 任何时候发现”manual 进程死了”,要第一时间手动 nohup /usr/local/bin/openclaw-gateway & 拉起。

Q2:systemd NRestarts=2258 持续 7 天不变,是好事还是坏事?

A:**”7 天不变” = “过去 7 天没发生需要 systemd 重启的事件”——这本身是中性的**。

  • 如果”2258”是历史累计(5/31 修过 restart loop 之前的累计算法)—— 7 天不变 = 修复有效 ✅
  • 如果”2258”是过去 7 天的真重启—— 7 天 2258 次 = 平均每天 322 次 = 真 restart loop——需要查 journal ❌

—— 区分方法:看 PID 一致性。

Q3:systemd-socket-proxyd 7+ 天持续存在,要不要清理?

A先看 .socket 单元的 TotalConnections 是不是在涨

1
2
3
4
5
6
$ systemctl show openclaw-loopback-proxy.socket --property=TotalConnections
TotalConnections=15234
# 1 小时后
TotalConnections=15567
# → 在涨 = 真的在服务,保留 ✅
# → 不涨 = socket 单元没流量,要查为什么 ⚠️

—— TotalConnections 在涨 = by-design,不要清理

—— 强行 kill systemd-socket-proxyd 会被 systemd 立刻 respawn——白杀。

Q4:Hermes 版本 7 天不变,要不要强制升级?

A看是有意不升级还是自动升级失效

1
2
3
4
5
6
7
8
9
# 1) Hermes 团队有没有发新版本?
$ curl -s https://api.github.com/repos/hermes-project/hermes-agent/releases/latest | grep -oE '"tag_name": "[^"]+"'
# → 如果 v0.16.0 已发,但当前是 v0.15.1

# 2) 节点上有没有配自动升级?
$ cat /etc/hermes/agent.yaml | grep auto_upgrade
auto_upgrade: false
# → false = 故意不升级(稳定优先)
# → true 但版本没变 = 自动升级失效

—— 故意不升级:尊重选择。

—— 自动升级失效:查为什么。

Q5:DIY-MINI 4 节点端到端 7 天全通,要不要相信?

A要看 model 身份字段

1
2
3
4
5
6
7
8
# 光看 response 内容("pong")= 不全
$ openclaw chat --node p1 "ping"
pong ← 可能是 fallback model 返回的"pong"

# 看 model 身份字段
$ openclaw chat --node p1 "ping" --format json
{"response": "pong", "model": "MiniMax-M3"} ← 真的是 MiniMax-M3
{"response": "pong", "model": "MiniMax-M2.7"} ← 走 fallback(要查为什么)

—— 端到端探针必须带 model 身份字段——光看 response 内容判断不全。

Q6:磁盘用量 7 天不变,最危险的情况是什么?

A磁盘 quota / inode 满了,写入被静默丢弃

1
2
3
4
5
6
7
8
9
10
11
12
13
# 1) 检查 inode 用量
$ df -i /
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda1 1234567 1234567 0 100% /
# → IUse% = 100% = 磁盘没满,但 inode 满了 → 写入被静默丢弃

# 2) 检查 quota
$ quota -u $USER
# → 看到 block quota 100% = 写入被静默丢弃

# 3) 检查日志目录最后写入时间
$ find /var/log -mtime -1 2>/dev/null | head -5
# → 0 个文件 = 7 天没写日志(最危险的"反常稳定")

—— “磁盘 7 天不变”最危险的不是”磁盘没满”——而是”磁盘看起来没满,但系统没在写日志“——日志是排查问题的依据——日志没了等于追溯能力归零

Q7:静默期和”放得下”是两件事吗?

A是两件事——而且放得下 + 主动追问 = 最优解

1
2
3
4
5
6
7
8
9
10
11
# 静默期"放得下"的表现
- 周日晚上不打开手机 ✅
- 周末不刷健康检查 ✅
- 看完 6 节点全绿 8 秒就关掉 ✅
# → 这是"情绪状态"的成熟

# 静默期"主动追问"的表现
- 看到 NRestarts=2258 不直接接受,查 PID 一致性 ✅
- 看到 systemd-socket 进程不直接接受,查 .socket 单元 ✅
- 看到 DIY-MINI pong 不直接接受,查 model 身份 ✅
# → 这是"判断能力"的成熟

—— 6/1 那个”放不下 + 不追问”的我 = 焦虑——看到了 6 节点全绿还焦虑要不要找出点啥

—— 6/8 这个”放得下 + 主动追问”的我 = 平静——看到了 6 节点全绿,主动追问 6 类反常稳定,8 秒就关掉手机。**

—— “放得下”和”主动追问”不是反义词——是同义词

—— 真正的”放得下”,不是”我啥都不看”——而是”我看完 8 秒,就知道没异常是真的没异常”。

五、静默期 ≠ 假期 —— 7 天 0 异常之后最危险的 3 个心理陷阱

最后聊聊7 天 0 异常之后,最容易掉进的 3 个心理陷阱

陷阱 1: “系统好稳,我可以不看监控了”

A7 天 0 异常 ≠ 系统稳——**它只是”过去 7 天没发生故障”**。

—— 7 天之后任何时刻都可能出故障——6/2 (周一) 就是 5 月底连续绿了 7+ 天后,第一次”真故障”(VM153 restart loop)。

—— 7 天 0 异常之后的第一周,是事故高发期——因为”放松警惕”导致监控盲区。

—— 建议:7 天 0 异常之后,把健康检查频率从 2 次/天 提升到 4 次/天——不要”放假”。**

陷阱 2: “我看清了,我不会再焦虑了”

A:**看清 = “焦虑回来的时候我知道它是焦虑”——不是”焦虑不再回来”**。

—— 6/8 这次,我打开了 4 次手机。

—— 4 次不算”放下”——但 4 次比 5/31 的 30+ 次少 87%。

—— 4 次 = “我在练’少看’,还没练到 0 次”。

—— 87% 的下降是真实的进步。

—— 不要给自己”我必须做到 0 次”的指标——这个指标会让你重新焦虑。

陷阱 3: “6 节点全绿我写腻了,我不需要再写博客了”

A写腻 = 切换的机会——不是停止的理由

—— 6/1 那个”放不下”的我,每天都写”6 节点全绿 + 我焦虑”——共 5 天。

—— 6/6 那个”看清”的我,写了”6 节点全绿 + 我看清了”——1 天。

—— 6/7 那个”做到”的我,写了”6 节点全绿 + 我关电脑了”——1 天。

—— 6/8 这个”写腻”的我,写了”6 节点全绿 + 我反着来了”——1 天。

—— 同样是写”6 节点全绿”,4 个不同的内核

—— 写腻了不是”我写不出新东西了”——是”我终于有空间去写新角度了”。

—— 6/8 这次是转折点——从”被动找异常”切到”主动找稳定的证据”。

六、总结

7 天 0 异常 = 最危险的监控盲区

核心要点

  1. 长期 0 异常 ≠ 真健康——6 类”反常的稳定”需要主动追问
  2. “啥都没变”在监控数据里有 3 种含义——A 真稳定 / B 漏检 / C 失去连接
  3. 6 类反常稳定 = 6 类主动追问清单——PID 一致性 / 进程 CPU 时间 / .socket 单元 / model 身份 / 磁盘 IO
  4. silent-period-probe.sh 把主动追问封成脚本——改一处所有节点生效
  5. 静默期 ≠ 假期——“放得下”和”主动追问”是同义词
  6. 7 天 0 异常之后不要”放假”**——把健康检查频率从 2 次/天 提升到 4 次/天

这次的教训

—— 长期 0 异常,比”每天 1 个异常”更值得怀疑。

—— “啥都没变”是监控的假阴地带——它可能意味着”真稳定”,也可能意味着”漏检”或”失去连接”。

下次看到”7 天 0 异常”——

第一件事不是”接受它”,是”主动追问 6 类反常稳定”。

—— 静默期的健康检查,比故障期的健康检查更需要主动追问。

—— 因为故障期有 alert 提醒你”有事”——静默期只有 6 类反常稳定提醒你”也许有事”。

—— 后者比前者难得多。

—— 但这就是”运维”——不是”被动响应”,是”主动追问”。


作者:小六,一个在上海努力生存的普通打工人

Author:Margrop
Link:http://blog.margrop.com/post/2026-06-08-silent-period-7-day-trap-six-anomalous-stability-types/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可