前言
这篇博客记录了演进过程,缺少参考价值。建议直接查看下述项目并使用docker快速部署。
效果图:
| Light | Dark |
|---|---|
![]() | ![]() |
旧方案:ssh获取nvidia-smi输出
之前的前端经验停留在使用Python生成html,因此用我的小主机配置了一个GPU监控方案:
- 通过ssh命令获取nvidia-smi的输出,并将显存占用等信息从中解析出来。
- 根据占用GPU进程的pid,通过ps命令获取用户和命令。
- 使用Python将上述信息输出为markdown,并通过Markdown输出为html。
- 配置cron每分钟执行上述步骤,在nginx中配置网页root为html所在目录。
对应的代码如下:
这个方案有几个很明显的缺点,更新频率较低,并且完全依赖后端更新,无论有没有人访问都要不停地刷新数据。
新方案:前后端分离
其实一直想实现一个前后端分离的GPU监控,每个服务器上运行一个fastapi,有请求时就返回所需的数据。最近开发的南哪充电让我有了信心去开发一个前端,从api中获取数据并渲染在页面上。
fastapi后端
最近无意间发现nvitop是支持Python调用的,原来一直以为只能通过命令可视化数据来着。
挺好,这样就能更加方便地获取所需的数据了,代码量大幅降低! ( •̀ ω •́ )✧
不过有一个麻烦的问题是我们实验室的服务器是在路由器下的,而路由器并不在我的控制下,端口只转发了ssh的。
这里我选择了使用frp,将每个服务器的API端口映射到我校内的小主机上。正好我的小主机配置了不少web服务,也方便通过域名访问API。
之前傻掉了,其实完全可以使用ssh(ssh -fN -L 8000:localhost:8000 user@ip)进行端口映射,这样就可以用删除代码中的frp相关内容,使用docker启动web端也会更加容易。
代码中有3个环境变量:
SUBURL: 用于配置api的路径,比如指定为服务器名称之类的。FRP_PATH: frp及其配置所在的路径,用于将API所在端口映射到我的校内小主机。如果你们的服务器可以直接访问到,那删掉相关函数,将最后一行改为0.0.0.0,之后通过IP(或者另外给每个服务器配置域名)访问就行了。PORT: API所在的端口。
这里我只写了两个接口 ,实际也只用到了一个
/count: 返回有多少给GPU。/status: 返回具体的状态信息,返回数据可见下面的示例。不过这里我另外写了两个可选的参数:idx: 逗号隔开数字,可以获得指定GPU的状态。process: 用于筛选返回的进程,我使用时直接设定为C,只展示计算任务。
vue实现的前端
这里先偷个懒 ,其实是因为不会,暂时先照抄了原本用Python生成的UI。
npm run build 顺利拿到release的文件,把nginx的root配置到该文件夹下就大功告成了。
实现的效果: https://nvtop.njucite.cn/
虽然UI还是一样的丑,但是至少可以动态刷新了,好耶!
新UI
先把饼画在这里,待我学成归来。( ̄_, ̄ )
更美观的UI(这一点有没有达成我也不确定了,我是设计的废物)
增加利用率折线图
支持夜间模式
2024/12/27:使用nextjs把上面的TODO都完成了,此外还实现了隐藏部分主机的功能,并将隐藏主机设定为cookie,方便下次再打开时展示相同的状态。
2025/03/11:nextjs更新了邮箱登录功能,仅限授权用户访问。
2025/09/18:把代码整理了一下,现在功能基本完善并且方便其他人直接部署了。
完整代码见:

