ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Codex 100个真实案例 - 用AI做服务器监控面板(CPU/内存/磁盘一目了然)

Codex 100个真实案例 - 用AI做服务器监控面板(CPU/内存/磁盘一目了然) 1. 从零搭一个服务器监控面板为什么我选 Codex Flask服务器监控面板这个东西说白了就是把 CPU、内存、磁盘这些指标采集出来再用图表画出来。听起来简单但真动手写的时候采集脚本、数据库存储、告警逻辑、前端图表每一块都有坑。我之前用传统方式写过一版光是把 psutil 的各个 API 调通、把 ECharts 的配置项对齐就花了大半天。这次我换了个思路用 Codex 来生成整个项目的骨架和核心逻辑。Codex 是 OpenAI 推出的代码生成模型能根据自然语言描述直接产出可运行的 Python 代码。它适合谁适合那些想快速验证想法、不想在样板代码上耗时间的开发者。你不需要从零写每一行只需要把需求描述清楚Codex 会把采集、存储、API、前端这一整条链路串起来。我实测下来用 Codex 生成一个完整的 Flask 监控面板从项目初始化到本地跑通大概 20 分钟。这篇文章我会把每一步的提示词、生成的代码、以及我踩过的坑都写出来你可以直接跟着操作。核心检索词就三个Codex、服务器监控、Python Flask。下面进入正题。2. 前置准备TaoToken 接入与 Codex 环境配置在开始写代码之前你需要先把 Codex 的调用环境配好。我用的方式是走 TaoToken 的 API 网关它兼容 OpenAI 的接口格式配置起来比较直接。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentAPI 地址是 https://taotoken.net/api。2.1 获取 API Key 并配置环境变量首先去 TaoToken 的控制台创建一个 API Key。打开 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite登录后进入 API Keys 页面点创建新密钥。创建完成后复制那串 key后面配置要用。拿到 key 之后我建议用环境变量的方式管理不要硬编码在代码里。在终端执行export TAOTOKEN_API_KEYsk-你的实际key如果你用的是 Codex CLI它的配置文件通常在~/.codex/config.toml。你需要把 Base URL 指向 TaoToken 的 API 地址同时指定模型 ID。下面是一个可复制的 TOML 配置片段# ~/.codex/config.toml model gpt-4o model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api chat这里三个关键件必须对齐Base URL 是https://taotoken.net/apiKey 从环境变量TAOTOKEN_API_KEY读取Model ID 填gpt-4o或你账号下可用的模型。如果你用的是 Cline 或者 Claude Code 这类工具配置逻辑类似都是把 Base URL 和 Key 填对。2.2 验证 Codex 是否可用配置完成后在终端跑一条简单命令验证codex 用 Python 写一个打印当前时间的函数如果能看到 Codex 返回代码说明接入成功。如果报 401 错误检查 key 是否复制完整如果报连接超时检查 base_url 是否写成了https://taotoken.net/api而不是带其他路径。2.3 安装项目依赖监控面板需要几个核心库Flask 做 Web 框架psutil 采集系统指标APScheduler 做定时任务requests 用于多服务器拉取。在项目目录下创建requirements.txtflask3.0.0 psutil5.9.6 apscheduler3.10.4 requests2.31.0然后执行pip install -r requirements.txt。Python 版本建议 3.10 以上我用的是 3.11psutil 和 Flask 都兼容。3. 可复制配置用 Codex 生成采集脚本与 Flask 路由这一节是核心我会把 Codex 生成的采集模块、数据库模块、Flask 路由和前端配置都贴出来。你可以直接复制到对应文件里。3.1 项目结构初始化先让 Codex 生成项目骨架。在终端输入codex 创建一个服务器监控项目 server-monitor使用 Python Flask ECharts。项目结构app.py 主入口collector.py 采集模块models.py 数据库模型alert.py 告警模块config.py 配置文件static/js/dashboard.js 前端逻辑templates/index.html 页面模板。生成完整的目录结构和基础代码。Codex 会生成类似这样的结构server-monitor/ ├── app.py ├── collector.py ├── models.py ├── alert.py ├── config.py ├── requirements.txt ├── static/ │ └── js/ │ └── dashboard.js └── templates/ └── index.html3.2 采集模块 collector.py采集模块负责从 psutil 拿数据。核心方法包括 CPU 使用率、内存占用、磁盘分区和 I/O、网络收发速率。下面是我整理后的关键代码# collector.py import psutil import platform import time from datetime import datetime class SystemCollector: def __init__(self): self._last_net_io psutil.net_io_counters() self._last_net_time time.time() self._last_disk_io psutil.disk_io_counters() self._last_disk_time time.time() def get_cpu_info(self): cpu_percent psutil.cpu_percent(interval1) per_cpu psutil.cpu_percent(interval0, percpuTrue) freq psutil.cpu_freq() freq_info { current: round(freq.current, 2) if freq else 0, min: round(freq.min, 2) if freq else 0, max: round(freq.max, 2) if freq else 0 } try: load_avg list(psutil.getloadavg()) except (AttributeError, OSError): load_avg [0, 0, 0] return { percent: cpu_percent, per_cpu: per_cpu, count_logical: psutil.cpu_count(logicalTrue), count_physical: psutil.cpu_count(logicalFalse), freq: freq_info, load_avg: load_avg } def get_memory_info(self): mem psutil.virtual_memory() swap psutil.swap_memory() return { total_gb: round(mem.total / (1024**3), 2), used_gb: round(mem.used / (1024**3), 2), available_gb: round(mem.available / (1024**3), 2), percent: mem.percent, swap_percent: swap.percent } def get_disk_info(self): partitions [] for part in psutil.disk_partitions(allFalse): try: usage psutil.disk_usage(part.mountpoint) partitions.append({ device: part.device, mountpoint: part.mountpoint, fstype: part.fstype, total_gb: round(usage.total / (1024**3), 2), used_gb: round(usage.used / (1024**3), 2), free_gb: round(usage.free / (1024**3), 2), percent: usage.percent }) except PermissionError: continue current_io psutil.disk_io_counters() current_time time.time() elapsed current_time - self._last_disk_time io_info {} if current_io and elapsed 0: io_info { read_speed_mb: round( (current_io.read_bytes - self._last_disk_io.read_bytes) / elapsed / (1024**2), 2 ), write_speed_mb: round( (current_io.write_bytes - self._last_disk_io.write_bytes) / elapsed / (1024**2), 2 ) } self._last_disk_io current_io self._last_disk_time current_time return {partitions: partitions, io: io_info} def get_network_info(self): current_io psutil.net_io_counters() current_time time.time() elapsed current_time - self._last_net_time io_info {} if elapsed 0: io_info { send_speed_kb: round( (current_io.bytes_sent - self._last_net_io.bytes_sent) / elapsed / 1024, 2 ), recv_speed_kb: round( (current_io.bytes_recv - self._last_net_io.bytes_recv) / elapsed / 1024, 2 ), errin: current_io.errin, errout: current_io.errout } self._last_net_io current_io self._last_net_time current_time return {io: io_info} def get_system_overview(self): return { timestamp: datetime.now().isoformat(), hostname: platform.node(), os: f{platform.system()} {platform.release()}, uptime_seconds: time.time() - psutil.boot_time(), cpu: self.get_cpu_info(), memory: self.get_memory_info(), disk: self.get_disk_info(), network: self.get_network_info() }这段代码的关键点在于网络和磁盘速率的计算通过记录上一次的 I/O 计数和时间戳用差值除以时间间隔得到速率。这是生产环境常用的做法比直接读瞬时值准确。3.3 配置文件 config.py配置文件里我定义了采集间隔、告警阈值、数据库路径和服务器列表。下面是一个可复制的 JSON 风格配置片段实际是 Python 字典# config.py import os SERVER_PORT 5050 DEBUG True SECRET_KEY os.environ.get(SECRET_KEY, server-monitor-secret-key-2024) COLLECT_INTERVAL 5 DATA_RETENTION_DAYS 7 CLEANUP_INTERVAL_HOURS 1 DB_PATH os.path.join(os.path.dirname(__file__), data, monitor.db) os.makedirs(os.path.dirname(DB_PATH), exist_okTrue) ALERT_RULES { cpu: { enabled: True, warning_threshold: 70, critical_threshold: 90, duration_seconds: 60, description: CPU 使用率告警 }, memory: { enabled: True, warning_threshold: 80, critical_threshold: 95, duration_seconds: 30, description: 内存使用率告警 }, disk: { enabled: True, warning_threshold: 80, critical_threshold: 95, duration_seconds: 0, description: 磁盘使用率告警 } } MONITORED_SERVERS [ { name: 本机, host: 127.0.0.1, port: 5050, enabled: True, description: 本地开发服务器 } ] REMOTE_TIMEOUT 5 NOTIFICATION { console: True, webhook: False, webhook_url: , cooldown_seconds: 300 }这里有个细节duration_seconds表示指标必须持续超过阈值多少秒才触发告警。CPU 设了 60 秒内存设了 30 秒磁盘设了 0 秒因为磁盘空间不会瞬间波动。这个设计能有效避免误报。3.4 Flask 路由 app.pyFlask 部分提供实时数据、历史数据、告警记录和服务器列表四个 API。核心代码如下# app.py from flask import Flask, render_template, jsonify, request from apscheduler.schedulers.background import BackgroundScheduler from collector import SystemCollector from models import MonitorDB from alert import AlertEngine import config app Flask(__name__) app.config[SECRET_KEY] config.SECRET_KEY collector SystemCollector() db MonitorDB() alert_engine AlertEngine(db) _latest_data {} def collect_and_save(): global _latest_data try: data collector.get_system_overview() server_name config.MONITORED_SERVERS[0][name] db.save_metrics(server_name, data) alerts alert_engine.check(server_name, data) _latest_data data _latest_data[active_alerts] alerts except Exception as e: print(f采集任务异常: {e}) app.route(/) def index(): return render_template(index.html, serversconfig.MONITORED_SERVERS) app.route(/api/realtime) def api_realtime(): global _latest_data if not _latest_data: _latest_data collector.get_system_overview() return jsonify({code: 200, data: _latest_data}) app.route(/api/history) def api_history(): hours request.args.get(hours, 1, typeint) server_name request.args.get(server, config.MONITORED_SERVERS[0][name]) data db.get_metrics_history(server_name, hours) return jsonify({code: 200, data: data, count: len(data)}) app.route(/api/alerts) def api_alerts(): hours request.args.get(hours, 24, typeint) server_name request.args.get(server, None) alerts db.get_alerts(server_name, hours) return jsonify({code: 200, data: alerts, count: len(alerts)}) if __name__ __main__: scheduler BackgroundScheduler() scheduler.add_job(collect_and_save, interval, secondsconfig.COLLECT_INTERVAL) scheduler.start() print(f监控服务启动中... 面板地址: http://localhost:{config.SERVER_PORT}) app.run(host0.0.0.0, portconfig.SERVER_PORT, debugconfig.DEBUG, use_reloaderFalse)注意最后一行use_reloaderFalse。如果开启 Flask 的自动重载APScheduler 会被初始化两次导致采集任务重复执行。这个坑我踩过数据会翻倍。3.5 前端 ECharts 配置前端用 ECharts 画仪表盘、折线图、饼图和柱状图。核心逻辑在static/js/dashboard.js里每 5 秒调一次/api/realtime更新图表数据。下面是一个仪表盘的配置片段// static/js/dashboard.js const cpuGaugeChart echarts.init(document.getElementById(cpu-gauge)); function updateCpuGauge(percent) { cpuGaugeChart.setOption({ series: [{ type: gauge, startAngle: 220, endAngle: -40, min: 0, max: 100, detail: { formatter: {value}%, fontSize: 24, color: #58a6ff }, axisLine: { lineStyle: { width: 15, color: [[0.7, #3fb950], [0.9, #d29922], [1, #f85149]] } }, pointer: { itemStyle: { color: #58a6ff }, width: 4 }, data: [{ value: percent, name: CPU }] }] }); } async function fetchData() { const resp await fetch(/api/realtime); const result await resp.json(); const data result.data; updateCpuGauge(data.cpu.percent); // 其他图表更新逻辑... } setInterval(fetchData, 5000); fetchData();仪表盘的颜色分段是绿、黄、红对应正常、警告、严重三个区间。这个视觉反馈很直观一眼就能看出服务器状态。4. 验证请求本地启动后逐项核对指标刷新与告警阈值代码写完之后启动服务验证。在项目目录下执行python app.py你会看到类似输出监控服务启动中... 面板地址: http://localhost:5050 * Running on http://0.0.0.0:5050打开浏览器访问http://localhost:5050你应该能看到深色主题的监控面板。下面逐项核对。4.1 核对实时指标刷新面板顶部有五个卡片主机名、CPU 使用率、内存使用率、磁盘使用率、运行时间。每 5 秒自动刷新一次。你可以打开浏览器开发者工具的 Network 面板观察/api/realtime请求是否每 5 秒发一次返回的 JSON 里cpu.percent是否在变化。用 curl 直接验证 APIcurl http://localhost:5050/api/realtime | python -m json.tool返回结果应该包含cpu、memory、disk、network四个字段。如果cpu.percent是 0可能是 psutil 第一次调用还没采样完成等几秒再试。4.2 核对历史数据查询访问http://localhost:5050/api/history?hours1应该返回最近 1 小时的指标记录。如果刚启动不久数据点会少一些但结构应该完整。每条记录包含timestamp、cpu_percent、memory_percent、disk_percent等字段。4.3 核对告警阈值触发告警验证需要模拟高负载。在 Linux 或 macOS 上可以用yes命令占满 CPUyes /dev/null yes /dev/null yes /dev/null yes /dev/null 开四个后台进程后CPU 使用率会飙升。等 60 秒因为配置里duration_seconds是 60再查告警记录curl http://localhost:5050/api/alerts?hours1如果看到alert_type为cpu、level为warning或critical的记录说明告警逻辑正常。测试完记得清理killall yes4.4 核对磁盘和网络图表磁盘分区使用率用柱状图展示每个分区一根柱子颜色根据使用率变化。网络收发速率用双折线图展示发送和接收各一条线。你可以在服务器上跑一个下载任务观察网络折线是否有波动。5. 本篇常见错排查401、local proxy failed、reading choices 等报错处理这一节整理我在配置和运行过程中遇到的真实报错以及对应的解决方法。5.1 401 Unauthorized报错信息Error: 401 Unauthorized或AuthenticationError: Incorrect API key provided原因API Key 没配置对或者环境变量没生效。解决检查~/.codex/config.toml里的env_key是否指向正确的环境变量名。然后在终端执行echo $TAOTOKEN_API_KEY确认能打印出 key。如果为空重新export一次。另外检查 Base URL 是否写成了https://taotoken.net/api不要多加斜杠或路径。5.2 local proxy failed报错信息local proxy failed: connection refused或proxy error原因本地网络配置有问题或者请求被拦截。解决先确认本机网络能正常访问https://taotoken.net/api。可以用curl -I https://taotoken.net/api测试连通性。如果返回 200 或 401说明网络通。如果超时检查防火墙或 DNS 设置。注意不要使用任何非官方的网络工具直接走正常网络即可。5.3 reading choices 报错报错信息Error reading choices: unexpected end of JSON input或failed to parse response原因API 返回的响应格式不符合预期通常是模型 ID 写错了或者请求体格式不对。解决检查config.toml里的model字段确认填的是账号下可用的模型 ID。如果用的是gpt-4o确认 TaoToken 控制台里这个模型是启用的。另外检查wire_api是否设为chat不要设成responses。5.4 OAuth 相关报错报错信息OAuth token expired或refresh token failed原因如果你用的是 Claude Code 或类似工具OAuth 令牌过期了。解决重新走一遍授权流程。在 Claude Code 里执行claude login按提示重新授权。如果用的是 API Key 模式检查 key 是否被禁用或额度用完。登录 TaoToken 控制台 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 查看用量。5.5 Flask 启动后端口被占用报错信息OSError: [Errno 48] Address already in use原因5050 端口被其他程序占用了。解决改config.py里的SERVER_PORT为其他端口比如 5051。或者用lsof -i :5050找到占用进程并结束它。5.6 数据库写入报错报错信息sqlite3.OperationalError: database is locked原因多个线程同时写 SQLite 导致锁冲突。解决models.py里已经加了线程锁_lock确保同一时间只有一个线程写入。如果还报错检查是否有多个 Flask 进程同时运行。用ps aux | grep app.py查看如果有多个kill 掉多余的。6. 语义一致 CTA用 TaoToken 接入 Codex 继续扩展你的监控面板监控面板跑通之后你可以继续用 Codex 扩展功能。比如加一个进程 Top10 表格、加邮件告警、加多服务器聚合视图。这些都可以通过自然语言描述让 Codex 生成代码。如果你还没配置 Codex 环境建议先走一遍 TaoToken 的接入流程。API Key 在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 创建接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 查看。模型对话功能可以直接在 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 体验适合快速验证提示词效果。如果你打算长期用 Codex 做编码和 Agent 任务Coding Plan 会更划算详情在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite。Claude Code 用户可以参考 https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaude-code-anthropicutm_campaignrewrite 的接入说明。回到监控面板本身我最后再分享一个实用技巧把COLLECT_INTERVAL设成 5 秒是本地开发的推荐值如果部署到生产服务器建议改成 10 到 15 秒减少对业务进程的影响。告警的cooldown_seconds设成 300 秒避免同一问题反复通知。数据库保留 7 天数据配合每小时清理一次SQLite 文件不会膨胀太快。这些参数你都可以在config.py里按需调整。
返回列表