不装 agent,一条命令采全服务器指标——Shellby 的监控
Shellby 复盘:没有采集端,纯 SSH 采 CPU/内存/磁盘/负载,把五类指标打包成一条命令。
Shellby 连上服务器后能实时看 CPU、内存、磁盘、负载和进程 Top。做这个功能有个硬约束:不能在服务器上装任何采集 agent。用户拿它连的是别人的、临时的、不允许乱装东西的机器,监控只能靠 SSH 本身能做的事——跑命令、读输出。这篇讲怎么用一条命令采全所有指标,以及解析要怎么写才经得起各种发行版。
一条命令,别攒五次往返
采五类指标最直觉的写法是发五条命令:一条读 CPU、一条读内存……但每条命令都是一次 SSH 往返,移动网络下五次往返的延迟叠起来很难看,而且要每 3 秒刷一次。
所以把五类指标打包成一条命令,一次 exec 拿全,用一个不会在正常输出里出现的分隔符隔开各段:
cat /proc/loadavg; echo '@@SEC@@'; cat /proc/stat; echo '@@SEC@@'; \
free -b; echo '@@SEC@@'; df -kP; echo '@@SEC@@'; \
ps -eo pid,pcpu,pmem,comm --sort=-pcpu | head -11
一次往返拿回全部五段,客户端按 @@SEC@@ 切开分别解析。五次往返压成一次,延迟和开销都降下来。
优先读 /proc——它是稳定的、格式可解析的内核接口,比各种 top/vmstat 的人类可读输出好解析得多。BSD/macOS 远端的命令差异留作后续适配(它们没有 /proc)。
CPU 使用率要两次采样做差
有个容易错的点:CPU 使用率不能只读一次。
/proc/stat 给的是开机以来各种 CPU 时间的累计值(用户态、系统态、空闲、iowait……),不是「当前使用率」。要算使用率,得采两次、做差:
idle = idle + iowait
total = 所有字段之和
使用率 = 1 - Δidle / Δtotal
也就是记住上一次的 idle 和 total,这次减上次,用空闲时间的增量占总增量的比例,反过来就是使用率。第一次采样时没有「上一次」,只能等第二次才有数——这决定了监控刚打开时 CPU 那一格会有一拍延迟。
其余几类直接解析:内存从 free -b 取 total/used,磁盘从 df -kP(1K 块要乘 1024),负载取 /proc/loadavg 前三个值,进程从 ps 取,注意 comm(命令名)可能含空格,得把末尾字段 join 回去。
解析器写成纯函数,字段不够就降级
解析这块全部写成纯函数——输入一段文本、输出结构化指标,不碰任何 IO 或状态。这么写有两个好处:
其一,好单测。真机连 Linux 联调需要环境,但解析逻辑用文本夹具就能测——喂各种真实/畸形的 /proc/stat、free、df 输出,断言解析结果。这也是为什么本机 macOS 的 sshd 没有 /proc、没法端到端测时,解析器仍然能用 Linux 文本夹具充分覆盖。
其二,好降级。服务器五花八门,某个发行版的 ps 可能没有某个字段、free 的格式可能略有不同。解析器的原则是:字段不够就 continue 或返回 nil,绝不崩;整段缺失(比如切出来不足五段)直接返回、不往下走。监控少显示一格,比整个功能崩掉强得多。采集不可信数据时,解析器的健壮性比它的精确性更重要——你没法保证每台服务器的输出都合你的格式。
开销:轮询要克制,历史只留内存
实时监控每隔几秒采一次,得控制开销:
- 轮询间隔默认几秒一次,不能太密——每次都是一条真实的 SSH 命令,太频繁既费流量又给服务器添负担;
- CPU 折线的历史点只在内存里留最近 60 个,不持久化——监控是个临时看一眼的东西,没必要落库;
- 监控面板关掉就停轮询——它是弹出来看的,靠面板的生命周期停采集,不看了就不采。
这些都是「实时功能」的通用纪律:刷新频率、历史长度、什么时候停,每一个都得主动定,否则一个后台一直在跑的轮询就是持续的流量和电量消耗。
小结
不装 agent 做服务器监控,几条经验:
- 打包成一条命令:五类指标用分隔符拼成一条 exec,一次往返拿全,别攒五次往返的延迟;
- 优先读
/proc:内核接口稳定可解析,比人类可读的工具输出好对付; - 累计值要做差:CPU 使用率得两次采样算增量比例,不是读一次就有;
- 解析器写成纯函数:好单测(文本夹具即可,不依赖真机)、好降级(字段不够就跳过、绝不崩);
- 实时功能要克制:轮询间隔、历史长度、停止时机都主动定,别让它默默耗流量电量。
监控别人的服务器,你能依赖的只有 SSH 和对面内核愿意告诉你的那点文本。把这点文本榨干、解析得稳,就是全部功夫。
留言