v1.3.14: CPU每核MHz显示+四页测速(CPU运行速度/内存读写/硬盘读写/网络上下行)+最多5条历史自动删旧
This commit is contained in:
1 parent
f417f8b01a
commit
1aff3138cb
4 files changed
+333
-8
No files matched your search
@@ -0,0 +1,136 @@
|
||||
<h2>前言:飞牛自带的监控,为什么不够用</h2>
|
||||
<p>飞牛 NAS 自带的资源监控只有一个百分比数字:CPU 多少、内存多少,没了。但实际运维中真正要回答的问题是:<strong>是哪个进程在吃 CPU?内存被谁占了?CPU 烧到多少度?风扇转不转?这台机器的配置到底顶不顶得住?哪块盘快坏了?哪个端口被谁占着?</strong></p>
|
||||
<p>于是我写了 <strong>fnos-resmon(飞牛资源管理器)</strong>:一个单文件 Flask + psutil 的轻量监控面板,专为飞牛 NAS 设计,一条 docker 命令启动,浏览器打开 <code>http://NAS-IP:7031</code> 就能看,手机也能看。</p>
|
||||
<p>开源地址:https://gitea.88531.cn/jinghui/fnos-resmon</p>
|
||||
<h2>一、它能做什么</h2>
|
||||
<ul>
|
||||
<li><strong>CPU 面板</strong>:型号 / 架构 / 物理核 / 逻辑核 / 每核频率占用,进程级 CPU 排行(进程名 / PID / 用户 / 状态 / 线程数),点表头即排序</li>
|
||||
<li><strong>🌡️ 温度 / 🌀 风扇面板</strong>:11 路温度 + 风扇实时 RPM,超温变色预警,读不到的机器显示友好提示不报错</li>
|
||||
<li><strong>📊 负载诊断</strong>:1 分钟负载 ÷ 逻辑核数 = 单核负载,直接告诉你"顶得住还是顶不住",并点名头号吃 CPU 进程</li>
|
||||
<li><strong>🚀 一键优化系统</strong>:数据落盘 + 回收内存缓存 + 内存碎片整理,实测一次释放 500MB+</li>
|
||||
<li><strong>内存面板</strong>:每个进程 RSS / USS / SWAP 三列细分,物理内存槽位(容量 / 类型 / 频率 / 厂商)全展示,🧹 绿色大按钮一键回收内存</li>
|
||||
<li><strong>磁盘面板</strong>:SMART 健康 / 温度 / 通电时间 / 坏道重映射,阵列拓扑、挂载点用量、进程 IO 排行</li>
|
||||
<li><strong>网络面板</strong>:实时上下行速率、累计收发、连接数,所有 TCP 连接和侦听端口明细(进程 + 地址 + 状态),网卡驱动 / 速率 / 双工 / MTU</li>
|
||||
<li><strong>一键 kill 异常进程</strong>,右上角可调刷新间隔(3s / 5s / 10s / 30s / 60s)+ ⏸ 随时暂停</li>
|
||||
</ul>
|
||||
<h2>二、实现原理:容器里怎么读到宿主真实数据</h2>
|
||||
<p>监控跑在 Docker 里,默认只能看到容器自己的 namespace。要读宿主真实数据,靠三招:</p>
|
||||
<pre><code class="language-yaml">services:
|
||||
fnos-resmon:
|
||||
image: jpccr.ccs.tencentyun.com/jinghui/fnos-resmon:latest
|
||||
network_mode: host
|
||||
pid: host # 与宿主共享 PID 命名空间
|
||||
privileged: true
|
||||
volumes:
|
||||
- /proc:/host/proc:rw # 宿主 proc
|
||||
- /sys:/host/sys:ro # 宿主 sysfs(温度/风扇/网卡从这读)</code></pre>
|
||||
<p><strong>1. CPU / 内存 / 进程:psutil 重定向 PROCFS。</strong>启动时把 <code>psutil.PROCFS_PATH</code> 指向 <code>/host/proc</code>,之后所有 <code>psutil.process_iter / cpu_percent / virtual_memory</code> 读到的都是宿主数据:</p>
|
||||
<pre><code class="language-python">PROCFS = os.environ.get("PROCFS_PATH", "/host/proc")
|
||||
if os.path.isdir(PROCFS):
|
||||
psutil.PROCFS_PATH = PROCFS</code></pre>
|
||||
<p><strong>2. 网络:nsenter 进宿主 netns。</strong>容器即使 bridged 模式,直读 <code>/proc/net</code> 也只能看到容器自身。网络类数据统一经 <code>nsenter --target 1 --mount --net</code> 在宿主(PID 1)netns 里执行 <code>cat /proc/net/dev</code> 和 <code>ss -tunHn state all</code>,失败才回退到 psutil 容器视角:</p>
|
||||
<pre><code class="language-python">NSENTER = ["nsenter", "--target", "1", "--mount", "--net"]
|
||||
|
||||
def _host_ss():
|
||||
"""宿主 tcp/udp 连接+监听,经 nsenter 在宿主 netns 执行 ss"""
|
||||
out = _nsenter_run(["ss", "-tunHn", "state", "all"])</code></pre>
|
||||
<p>ss 行尾的 <code>("进程名",pid=1234,...)</code> 会被正则抠出来,再用进程表按 PID 补齐进程名,前 80 条连接 + 前 80 条监听返回前端。</p>
|
||||
<p><strong>3. 后台采样线程 + 2 秒缓存。</strong>进程 CPU 统计需要两次采样算差值,所以 <code>sample_procs()</code> 先全员 <code>cpu_percent(None)</code> 打点,sleep 1 秒后再读数,按 CPU 倒序,前端每 2 秒拿到的是缓存,不会每次请求都卡 1 秒:</p>
|
||||
<pre><code class="language-python">def sampler_loop():
|
||||
while True:
|
||||
try:
|
||||
sample_procs()
|
||||
except Exception:
|
||||
pass
|
||||
time.sleep(2)
|
||||
|
||||
threading.Thread(target=sampler_loop, daemon=True).start()</code></pre>
|
||||
<p>每个进程采集的字段:cpu / mem / rss / uss / swap / 线程数 / 用户 / 状态 / IO 读写 / 连接数。容器内 <code>/etc/passwd</code> 没有宿主用户,纯数字 uid 会经 <code>/host/etc/passwd</code> 还原用户名(5 分钟缓存)。</p>
|
||||
<h2>三、两个最实用的接口:负载诊断与一键优化</h2>
|
||||
<p><strong>GET /api/cpu/advise —— 配置顶不顶得住,一句话结论。</strong>公式很简单:<code>单核负载 = 1分钟load ÷ 逻辑核数</code>,分四档给结论,并点名最吃 CPU 的进程、给出扩容 / 杀进程 / 属正常的建议:</p>
|
||||
<pre><code class="language-python">@app.route("/api/cpu/advise")
|
||||
def api_cpu_advise():
|
||||
load = list(os.getloadavg()) # 1/5/15 分钟
|
||||
per_core = load[0] / logical # 单核负载
|
||||
# 四档:<0.7 轻松 / <1.0 饱和 / <2.0 吃力 / 更高 过载</code></pre>
|
||||
<p><strong>POST /api/sys/optimize —— 一键优化。</strong>依次做三件事:<code>sync</code> 数据落盘 → 写 <code>/host/proc/sys/vm/drop_caches</code> 回收 pagecache → 写 <code>/host/proc/sys/vm/compact_memory</code> 整理碎片。内存面板另有 <strong>POST /api/mem/drop</strong> 单独回收。零侵入:只调内核已有接口,不改系统文件。</p>
|
||||
<p><strong>GET /api/sensors —— 温度风扇。</strong>优先读 <code>/host/sys/class/hwmon</code>,回退 <code>/sys/class/hwmon</code>,<code>temp*_input ÷ 1000</code> 得摄氏度,<code>fan*_input</code> 即 RPM,label 优先用 <code>temp*_label</code>。超温阈值前端变色预警,风扇节点不存在(如纯 NAS 小主机无风扇上报)的机器返回空 + 友好提示,不阻塞主流程。</p>
|
||||
<h2>四、API 一览</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>方法</th>
|
||||
<th>路径</th>
|
||||
<th>作用</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>GET</td>
|
||||
<td><code>/api/cpu</code></td>
|
||||
<td>CPU 信息 + 每核占用 + 进程排行 + load</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GET</td>
|
||||
<td><code>/api/mem</code></td>
|
||||
<td>内存占用 + RSS/USS/SWAP 进程明细 + 槽位硬件</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GET</td>
|
||||
<td><code>/api/disk</code></td>
|
||||
<td>挂载用量 + SMART/温度/通电时间 + 阵列 + IO 排行</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GET</td>
|
||||
<td><code>/api/net</code></td>
|
||||
<td>网卡速率 + TCP/监听明细 + 硬件(驱动/MTU/双工)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GET</td>
|
||||
<td><code>/api/sensors</code></td>
|
||||
<td>11 路温度 + 风扇 RPM</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GET</td>
|
||||
<td><code>/api/cpu/advise</code></td>
|
||||
<td>负载诊断:四档结论 + 头号进程 + 建议</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>POST</td>
|
||||
<td><code>/api/sys/optimize</code></td>
|
||||
<td>一键优化:落盘 + 回收缓存 + 内存整理</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>POST</td>
|
||||
<td><code>/api/mem/drop</code></td>
|
||||
<td>一键内存回收</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>POST</td>
|
||||
<td><code>/api/kill</code></td>
|
||||
<td>结束异常进程(限宿主 PID)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GET</td>
|
||||
<td><code>/api/health</code></td>
|
||||
<td>健康检查</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2>五、部署:一条命令</h2>
|
||||
<pre><code class="language-bash">docker run -d --name fnos-resmon -p 7031:7031 --privileged \
|
||||
-v /proc:/host/proc:rw -v /sys:/host/sys:ro \
|
||||
jpccr.ccs.tencentyun.com/jinghui/fnos-resmon:latest</code></pre>
|
||||
<p>浏览器打开 <code>http://NAS-IP:7031</code> 即可。前端是单个静态页(改前端必须重建镜像),后端一个 <code>app.py</code> 约 1100 行,无数据库,开箱即用。</p>
|
||||
<h2>六、实测截图(v1.3.4 当前版本)</h2>
|
||||
<p>CPU 面板:63°C 红色预警、风扇 1200 转 RPM、负载诊断四档结论、一键优化按钮:</p>
|
||||
<p><img alt="CPU面板" src="https://img.88531.cn/i/2026/11/07/6aeeca97f31e3.png" /></p>
|
||||
<p>内存面板:RSS/USS/SWAP 三列细分 + 🧹 一键回收大按钮:</p>
|
||||
<p><img alt="内存面板" src="https://img.88531.cn/i/2026/11/07/6aeeca9a62947.png" /></p>
|
||||
<p>磁盘面板:3 盘 SMART 全 PASSED + 温度通电时间:</p>
|
||||
<p><img alt="磁盘面板" src="https://img.88531.cn/i/2026/11/07/6aeeca9d2b3a2.png" /></p>
|
||||
<p>网络面板:qbittorrent 482 连接一眼揪出吃带宽进程:</p>
|
||||
<p><img alt="网络面板" src="https://img.88531.cn/i/2026/11/07/6aeeca9f70e61.png" /></p>
|
||||
<h2>七、总结</h2>
|
||||
<p>飞牛自带监控解决"有没有",fnos-resmon 解决"是谁、多少度、顶不顶得住、能不能一键收拾"。核心就三招:<strong>psutil 重定向宿主 proc、nsenter 进宿主 netns 读网络、后台线程 2 秒缓存进程快照</strong>,剩下的都是把数据摆整齐。如果你也在飞牛上跑了很多 Docker 服务,装一个看看头号吃 CPU 的到底是谁 —— 八成有惊喜。</p>
|
||||
<p>镜像:<code>jpccr.ccs.tencentyun.com/jinghui/fnos-resmon:latest</code> | 开源:https://gitea.88531.cn/jinghui/fnos-resmon | 端口 7031,欢迎提 issue。</p>
|
||||
Reference in new issue
Block a user