🧪 摸鱼也能写监控大屏?用 Python + HTML 实现一个炫酷系统资源监控面板

💡 前言

上班无聊,想看点有意思的东西,又不想被老板发现我在"划水"?于是我就想着:不如搞个实时监控大屏,既能看看电脑在跑啥,又能假装自己在做性能分析 😎

说干就干,花了几个小时,我做出了一个:

  • ✅ 实时显示 CPU 使用率
  • ✅ 查看当前线程数
  • ✅ GPU 使用情况(支持 NVIDIA)
  • ✅ 磁盘读写速度
  • ✅ 网络上传下载速率
  • ✅ 显示资源占用 Top 10 进程
  • ✅ 支持暗黑/亮白主题切换
  • ✅ 超炫粒子背景动画

这篇文章我会从头讲起,带你一步步实现这个项目,适合前端 + 后端同学一起玩耍。代码全开源,可扩展性强,拿来装逼、学习、练手都 OK!


🧱 技术选型

整个项目分为两个部分:后端 + 前端

🔧 后端(Python)

功能 技术
WebSocket 通信 websockets
系统信息采集 psutil
GPU 监控 nvidia-smi(NVIDIA 显卡)
异步任务调度 asyncio

🖥️ 前端(HTML + JS)

功能 技术
实时数据更新 WebSocket 接收
数据展示 DOM 操作
主题切换 CSS 变量 + JS 控制
背景动画 Canvas 绘图

⚙️ 后端搭建:用 Python 获取系统资源

先上核心功能:我们要通过 Python 实时获取系统资源,并通过 WebSocket 发送给前端。

1. 安装依赖

bash 复制代码
pip install websockets psutil pythonnet

注意:GPU 功能需要你安装了 NVIDIA 驱动,并且能在命令行运行 nvidia-smi

2. 核心代码(server.py

py 复制代码
import asyncio
import websockets
import json
import psutil
import subprocess
import os

async def get_gpu_usage():
    gpus = []
    if os.name == 'nt':
        try:
            result = subprocess.check_output(
                ['nvidia-smi', '--query-gpu=index,name,temperature.gpu,utilization.gpu,memory.used,memory.total',
                 '--format=csv,noheader,nounits'])
            lines = result.decode('utf-8').strip().split('\n')
            for line in lines:
                parts = line.split(', ')
                gpus.append({
                    "id": parts[0],
                    "name": parts[1],
                    "temp": int(parts[2]),
                    "usage": int(parts[3]),
                    "mem_used": int(parts[4]),
                    "mem_total": int(parts[5])
                })
        except (subprocess.CalledProcessError, FileNotFoundError):
            pass
    return gpus


def get_top_processes(limit=10):
    processes = []
    for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent']):
        try:
            if proc.info['cpu_percent'] > 0:
                processes.append(proc.info)
        except psutil.NoSuchProcess:
            continue
    processes.sort(key=lambda p: p['cpu_percent'], reverse=True)
    return processes[:limit]


async def send_data(websocket):
    while True:
        data = {
            "gpus": await get_gpu_usage(),
            "logical_cores": psutil.cpu_count(logical=True),
            "system_threads": psutil.threading.active_count(),
            "cpu_usage": psutil.cpu_percent(interval=1),
            "top_processes": get_top_processes(10),
        }
        try:
            await websocket.send(json.dumps(data))
        except websockets.exceptions.ConnectionClosed:
            break
        await asyncio.sleep(1)


async def main():
    async with websockets.serve(send_data, "0.0.0.0", 8765):
        print("WebSocket server started on ws://localhost:8765")
        await asyncio.Future()  # run forever


asyncio.run(main())

🖼️ 前端页面:科技风 + 实时刷新 + 动画背景

前端主要负责接收 WebSocket 数据并渲染到页面上。

1. 页面结构设计

我们用了以下模块:

  • 系统资源卡片 (CPU、线程数等)
  • GPU 使用面板
  • Top 10 进程列表
  • 粒子背景动画
  • 主题切换按钮

2. 核心 HTML + JS 逻辑

html 复制代码
<script>
  const ws = new WebSocket("ws://localhost:8765");

  ws.onmessage = function(event) {
    const data = JSON.parse(event.data);

    document.getElementById("cpu").textContent = data.cpu_usage.toFixed(1) + "%";
    document.getElementById("threads").textContent = data.system_threads;

    // 更新 GPU 列表
    const gpuContainer = document.getElementById("gpu-container");
    gpuContainer.innerHTML = "";
    if (data.gpus && data.gpus.length > 0) {
      data.gpus.forEach(gpu => {
        const card = document.createElement("div");
        card.className = "card";
        card.innerHTML = `
          <div class="label">${gpu.name}</div>
          <div>温度:<strong>${gpu.temp}°C</strong></div>
          <div>使用率:<strong>${gpu.usage}%</strong></div>
          <div>显存:${gpu.mem_used}/${gpu.mem_total} MB</div>
        `;
        gpuContainer.appendChild(card);
      });
    }

    // 更新进程榜单
    const tbody = document.getElementById("process-table-body");
    tbody.innerHTML = "";
    data.top_processes.forEach((proc, index) => {
      const row = document.createElement("tr");
      row.innerHTML = `
        <td>${index + 1}</td>
        <td title="${proc.name}">${truncateString(proc.name, 25)}</td>
        <td>${proc.cpu_percent.toFixed(1)}</td>
        <td>${proc.memory_percent.toFixed(2)}</td>
      `;
      tbody.appendChild(row);
    });
  };

  function truncateString(str, maxLength) {
    return str.length > maxLength ? str.slice(0, maxLength) + "..." : str;
  }

  function toggleTheme() {
    document.body.classList.toggle('light-mode');
  }
</script>

🎨 页面美化与细节体验

为了让监控面板看起来更专业、更炫酷,我做了这些优化:

  • 使用现代渐变色背景和科技字体
  • 所有数据卡片加阴影、悬停放大
  • 表格支持横向滚动,避免溢出
  • GPU 卡片加载动画渐入效果
  • 进程名称过长自动省略
  • 主题切换按钮一键切换亮白/暗黑模式
  • Canvas 粒子背景增加动态感

📬 最后

如果你也觉得上班有点无聊,不妨动手试试做一个属于自己的"系统监控大屏"。说不定下次老板走过来看一眼,还以为你在做性能调优呢 😏

完整代码我已经整理好,欢迎查看或 Fork:👉 [GitHub 示例地址](你可以替换成你的仓库链接)

如果你喜欢这类"摸鱼也能写出花"的项目,欢迎关注我,后面还会带来更多有趣的小项目分享!


👋 我是沙瑞金,一个喜欢折腾、热爱分享的菜鸡。

平时爱写点工具、做点可视化界面,偶尔发发掘金,记录一下折腾的过程。

如果你也喜欢这种风格的文章,欢迎点赞、收藏、转发三连走一波!

相关推荐
wan_da_ren1 分钟前
JVM监控及诊断工具-GUI篇
java·开发语言·jvm·后端
【本人】6 分钟前
Django基础(一)———创建与启动
后端·python·django
lifallen28 分钟前
Kafka 时间轮深度解析:如何O(1)处理定时任务
java·数据结构·分布式·后端·算法·kafka
你的人类朋友1 小时前
【✈️速通】什么是SIT,什么是UAT?
后端·单元测试·测试
程序无bug3 小时前
后端3行代码写出8个接口!
java·后端
绝无仅有3 小时前
使用LNMP一键安装包安装PHP、Nginx、Redis、Swoole、OPcache
后端·面试·github
他日若遂凌云志3 小时前
C++ 与 Lua 交互全链路解析:基于Lua5.4.8的源码剖析
后端
martinzh3 小时前
MySQL功能模块探秘:数据库世界的奇妙之旅
后端
绝无仅有3 小时前
服务器上PHP环境安装与更新版本和扩展(安装PHP、Nginx、Redis、Swoole和OPcache)
后端·面试·github
喵个咪3 小时前
开箱即用的GO后台管理系统 Kratos Admin - 支持ElasticSearch
后端·微服务·go