19 KiB
192.168.1.37 监控与定时任务技术说明
版本:v1.3,2026 年 11 月 9 日。新增显卡数量设置和夜间节电计划,详见第 12 节。
1. 访问与登录
设备监控页面:http://192.168.1.37:8090
定时任务入口在“问题与维护”下方,也可通过左侧“定时任务”菜单定位。手机底部有同名入口。
硬件监控仍可直接查看。定时任务能够实际执行服务器操作,因此使用独立的管理员账号登录:
- 账号:
admin。 - 初始密码:见交付的
定时任务管理员登录信息.txt,本说明不包含密码。 - 登录最长有效 8 小时;修改密码后所有任务管理登录均失效。
- 此密码与 SSH root 密码相互独立,本次没有修改 SSH 密码。
页面只开放在原有局域网访问范围内。当前使用局域网 HTTP,适用于可信局域网;不应将这个具备 root 任务执行能力的入口直接映射到公网。将来如需远程公开访问,应先配置 HTTPS 和适当的访问控制。
2. 本次新增功能
“定时任务”支持:
- 新增、编辑、启用、停用和删除任务。
- 立即执行一次;这不会自动启用任务的定时计划。
- 停止本次执行;与停用后续调度分开处理。
- 查看下次计划时间、最近执行结果和是否正在执行。
- 查看单任务执行记录,以及包含已删除任务的全局执行记录。
- 查看开始/结束时间、耗时、退出码、标准输出和错误输出。
- 管理员登录、退出及修改密码。
执行方式有三种:
| 执行方式 | 如何填写 | 说明 |
|---|---|---|
| 直接输入命令 | 例如 /usr/bin/nvidia-smi |
使用 Bash 执行,支持管道和多行命令。 |
| 粘贴脚本内容 | 选择 Bash 或 Python 3,粘贴代码 | 可以导入本地 .sh、.py 或文本脚本到编辑框;保存后才会传给服务器。 |
| 服务器上的脚本文件 | 填写绝对路径和可选参数 | 可选择 Bash、Python 3 或按文件自身方式执行;最后一种要求文件具有执行权限。 |
执行身份固定为 root,因为重启服务器和维护证书通常需要管理员权限。它不是隔离的脚本沙箱:应只运行自己理解并信任的命令。
工作目录默认 /root,使用非交互执行环境,不继承某个 SSH 窗口的虚拟环境。PATH 包含常用系统目录和 /snap/bin;如需 Conda、venv 或自定义环境变量,应在脚本内明确设置。
3. 第一次添加任务
- 刷新页面,打开“定时任务”,点击“登录管理”。
- 使用交付文件中的
admin与初始密码登录。 - 点击“新增任务”,填写任务名称。
- 选择执行方式,输入命令、脚本或服务器脚本路径。
- 设置执行周期,点击“检查执行周期”核对下次时间。
- 保持“保存后启用”不勾选,先保存为停用状态。
- 如适合测试,点击“执行一次”,确认执行内容,查看执行日志。
- 核对结果后,再启用计划。
保存任务本身不会立即执行脚本。新任务默认停用。退出登录、关闭网页或重启网页服务不会停止已经启用的系统计划。
常用模板
新增窗口提供:
- 显卡状态检查:读取
nvidia-smi,结果保存在执行日志中。 - 服务器定时重启:示例命令为
systemctl reboot,默认周期是每周日 03:00,默认停用。启用或立即执行前都会提示可能中断计算任务。 - SSL 证书续签示例:检查已有的 Certbot/acme.sh 工具并调用其续签入口。它不会安装工具、申请新域名或替用户配置证书。先确认现有续签配置,以及是否已经有其他自动续签任务;Web 服务的重新加载应按实际服务配置。
本次部署没有创建或启用实际的服务器重启任务和证书续签任务,也没有执行这两类操作。
4. 执行周期
所有日历时间按 Asia/Shanghai,北京时间 UTC+8 处理,页面显示服务器当前时间。
| 周期 | 规则 |
|---|---|
| 每天 | 指定时、分。 |
| 每周 | 可选择一个或多个星期及时间。 |
| 每月 | 选择 1 至 31 日和时间;当月不存在该日期时跳过。 |
| 每隔若干分钟/小时 | 启用后先等待指定间隔;每次执行结束后重新计时,避免长任务造成重叠。 |
| 指定日期,仅执行一次 | 选择未来的日期和时间,精确到分钟;至少晚于保存时刻 30 秒。 |
| 自定义 Cron | 标准五段:分、时、日、月、周。支持 *、逗号、范围、步长及常见英文月/星期名。 |
Cron 示例:
0 3 * * * 每天 03:00
0 3 * * 0 每周日 03:00
0 3 1 * * 每月 1 日 03:00
*/30 * * * * 每小时的 00、30 分
不支持 L、W、#、? 等扩展语法,也不接受带秒的六段 Cron。日和星期同时指定时,按传统 Cron 的“任一满足”语义处理。
Cron 是日历触发,和“上次结束后再间隔 N 分钟”不同。例如长任务执行 10 分钟,再间隔 5 分钟,下一次大约在本次开始 15 分钟后。
开机、错过与长任务
- 日历任务设置
Persistent=false,服务器关机期间错过的执行时间不补跑,避免开机后补执行重启类任务。 - 同一个任务由固定 systemd 服务承载,并有文件锁,不会同时重叠执行两份。
- 一个任务执行超时后会被停止。默认最长 1800 秒,可在高级设置中改为 10 至 86400 秒。
- 关闭网页只会关闭查看界面,不会停止系统定时器。
- 本机历史上出现过时钟回拨。启用重启等任务前,应核对页面显示的服务器时间;定时调度依赖服务器时钟和系统校时状态。
部署验证时,服务器时区为 Asia/Shanghai,系统报告 NTPSynchronized=yes。
5. 看懂执行结果
| 显示 | 意义 |
|---|---|
| 尚未执行 | 没有记录到执行。 |
| 执行中 | 本次进程仍在运行。 |
| 执行成功 | 命令正常退出,退出码为 0。 |
| 执行失败 | 命令退出码非 0,或启动过程中发生错误。 |
| 超时已停止 | 达到设置的最长执行时间,已停止本次进程。 |
| 已停止 | 本次进程被停止,可能是手动操作或系统停止服务。 |
| 执行被中断 | 执行期间系统重启或进程中断,未取得完整结果。 |
成功只表示脚本返回了 0,不保证某个证书一定已更新、备份一定可恢复或某个业务结果一定正确;这些应结合脚本输出核对。
“停用”只取消将来的调度,不会强制中止已经开始的执行。“停止本次”会终止执行进程,脚本可能尚未完成修改,操作前会提示确认。
目前单任务窗口展示最近 40 次执行,全局窗口展示最近 80 次。服务器执行记录按 90 天清理;每次输出上限约 512 KiB,网页每次读取最后 128 KiB。输出与脚本快照还有合计 256 MiB 的空间限制,较旧文件可能提前清理,执行状态元数据仍保留至期限。
删除任务会停用计划并移除模块生成的定时器,保留已有执行记录。历史记录可在“全部执行记录”查看。
6. 参考与技术栈
界面参考 宝塔 Linux 面板 计划任务的组织方式:任务列表、执行周期、Shell 脚本、启停、手动执行和执行日志。本次功能自行编写,沿用已有监控页面的深色风格,没有安装宝塔,也没有复制其面板源码。
原监控布局仍参考:
| 部分 | 使用技术 |
|---|---|
| 监控与任务前端 | HTML、CSS、原生 JavaScript、原生 <dialog> 对话框。 |
| 曲线 | 原生 SVG,保留原有 CPU、内存、GPU 温度、功耗和利用率历史。 |
| 网页后端 | Python 3.12 标准库,ThreadingHTTPServer。 |
| 数据库 | SQLite,WAL 模式;监控数据与任务数据分库存储。 |
| 系统调度 | systemd .timer 和 .service,不是浏览器内的倒计时。 |
| 网页与特权服务通信 | 本机 Unix socket,限制连接进程身份。 |
| 管理密码 | 随机盐、PBKDF2-HMAC-SHA256,240000 次迭代。 |
| 登录态 | 内存会话、HttpOnly/SameSite=Strict Cookie;写操作同时检查 Origin 与 CSRF。 |
| 执行控制 | 独立进程组、文件锁、超时、停止信号、限量输出、执行审计。 |
没有新增 npm、pip 或外部 CDN 依赖。服务器不需要 Node.js;开发阶段使用 Node.js 检查 JavaScript 语法。
7. 为什么要拆成两个服务
flowchart LR
A[浏览器:监控与任务界面] --> B[hardware-dashboard\n普通账号\nHTTP 8090]
B --> C[(原监控数据库)]
B -->|本机 Unix socket\n验证会话与 CSRF| D[hardware-taskd\nroot 任务管理服务]
D --> E[(独立任务数据库\nroot 专用目录)]
D --> F[systemd 定时器]
F --> G[task_exec\n执行指定任务]
G --> H[执行日志与结果]
H --> D
硬件网页继续使用原来的 hardware-dashboard 普通账号。新增 root 服务只通过本机 Unix socket 接收经验证的任务操作,不额外开放网络端口。
任务内容不插入 systemd 的 ExecStart。生成的服务只启动固定的执行器和经过验证的任务 ID;执行器从 root 专用数据库读取任务内容。这避免任务名称、换行或参数变成 systemd 单元配置。
上传或粘贴的脚本文本会统一换行为 Linux 格式。服务器脚本路径和参数以独立参数列表传递;命令内容模式则按管理员输入交给 Bash 执行。
root 服务不是恶意脚本隔离环境。管理员既然有权输入 root 命令,就应当视为具有服务器管理员权限。
8. 文件与数据库位置
以下均在 192.168.1.37:
| 路径 | 内容 |
|---|---|
/opt/hardware-dashboard/server.py |
网页 HTTP 和监控 API;新增任务 API 代理。 |
/opt/hardware-dashboard/static/tasks.js |
任务表单、登录、启停、执行和日志交互。 |
/opt/hardware-dashboard/task_core.py |
校验、周期转换、任务数据库和 systemd 管理。 |
/opt/hardware-dashboard/taskd.py |
本机任务服务、会话验证、审计和清理。 |
/opt/hardware-dashboard/task_exec.py |
单次执行、输出、超时与退出结果。 |
/etc/systemd/system/hardware-taskd.service |
新增任务管理常驻服务。 |
/etc/systemd/system/hwjob-任务ID.timer |
本模块为已创建任务生成的定时器。 |
/etc/systemd/system/hwjob-任务ID.service |
对应的执行服务。 |
/run/hardware-taskd/control.sock |
普通网页与 root 服务之间的本机通信入口。 |
/etc/hardware-task-admin.json |
管理密码的盐与散列,仅 root 可读。 |
/var/lib/hardware-taskd/tasks.sqlite3 |
任务定义、执行元数据和审计。 |
/var/lib/hardware-taskd/scripts/ |
脚本内容模式的执行快照。 |
/var/log/hardware-taskd/ |
每次执行的输出日志,仅经管理登录读取。 |
/var/lib/hardware-dashboard/monitor.sqlite3 |
原来的性能和硬件日志数据库,继续保留。 |
/root/hardware-task-admin-login.txt |
初始登录信息的服务器副本,仅 root 可读。 |
原有 hwlog 命令、硬件采集器及性能历史继续运行。本模块只管理自己创建的 hwjob-* 单元,不接管现有 crontab、系统 timer 或其他面板任务。
9. 常用维护命令
# 查看网页服务与任务服务
systemctl status hardware-dashboard.service hardware-taskd.service
# 查看任务管理服务自身报错
journalctl -u hardware-taskd.service -n 50 --no-pager
# 查看本模块的全部系统定时器
systemctl list-timers --all 'hwjob-*.timer'
# 查看某个任务的系统层日志,任务 ID 可从页面或数据库查出
# 将下方 32 位 ID 替换成实际值,不要把说明文字直接输入命令
systemctl status hwjob-0123456789abcdef0123456789abcdef.service
# 重启网页服务:不会取消已启用的任务
systemctl restart hardware-dashboard.service
# 重启任务管理服务:已有网页登录会失效,系统定时器仍独立运行
systemctl restart hardware-taskd.service
忘记任务管理密码时,可通过 SSH 以 root 执行以下命令。新密码在交互输入,不放进命令行参数:
python3 /opt/hardware-dashboard/taskd.py password
systemctl restart hardware-taskd.service
只停止网页或任务管理进程,不等于停用计划。要停止后续执行,应先在页面将对应任务停用;需要立即中断时再使用“停止本次”。
10. 备份与回退
本次更新前的网页代码备份:/opt/hardware-dashboard-backup.vNWXhLKD/。
任务数据库与监控数据库分开。备份正在运行的 SQLite 应使用 SQLite 的备份接口,不能只复制主文件而忽略 WAL。备份任务数据库、管理密码散列和脚本/日志时,应继续保持 root 专用权限。
如需回退界面,先在页面停用所有不再需要的任务,再停止任务管理服务并恢复代码。只恢复旧网页代码不会自动删除或停用已经生成的系统定时器。
11. 已完成的验证
自动化测试
16 项本地和服务器测试通过,覆盖:
- 原监控数据、问题合并、时钟回拨及过期状态。
- 每日/每周/每月/间隔周期与 Cron 字段解析。
- Cron 日期和星期的 OR 语义、非法范围和步长。
- 任务名称与脚本内容不会成为 systemd 单元配置指令。
- 未登录和错误 CSRF 不会调用特权任务操作。
- 修改密码使所有旧会话失效。
- 日志读取量上限与路径编号验证。
服务器真实执行验证
使用明确命名的“部署验证”任务,确认了:
| 验证内容 | 实际结果 |
|---|---|
| 手动打印命令 | 成功,退出码 0。 |
| 指定日期自动触发 | 在计划时间由 systemd 自动执行,记录为 scheduled,退出码 0。 |
| Python 脚本内容 | 成功,输出 PYTHON_TASK_OK。 |
| 服务器已有文件执行 | 成功,输出 EXISTING_FILE_OK。 |
| 主动返回退出码 7 | 正确显示失败,保留错误输出。 |
| 10 秒超时 | 约 10 秒后停止,显示超时。 |
| 手动停止等待任务 | 正确停止并记录状态。 |
| 编辑、启用和停用 | 页面与系统定时器状态一致。 |
| 未登录、错误来源、错误 CSRF | 分别被 HTTP 401/403 拒绝。 |
这些测试仅打印信息或短暂等待,没有执行重启、关机、证书续签或修改现有业务配置。测试计划在交付前移除,历史中保留有“部署验证”字样的执行记录。
12. 显卡数量与夜间节电(2026 年 11 月 9 日)
显卡数量
在“设备总览”的“计算显卡”卡片中,选择“1 张显卡”或“2 张显卡”,再点击“保存”。使用已有任务管理员账号登录后,设置保存到 /etc/hardware-watch.json,刷新网页、重启服务和重启服务器后仍有效。多个浏览器共用服务器上的设置。
保存会更新 expected_gpu_count 并清空 expected_gpu_uuids。监控随后按 NVIDIA 显卡数量检查,不再要求原来的 P100 UUID;可更换为 V100 等受当前驱动支持的 NVIDIA 显卡。温度、供电、驱动异常、PCIe 通信错误继续检测。选择 2 张而实际仅检测到 1 张时,仍会报缺卡。
页面通过 /api/tasks/gpu-count 调用已有 root 任务代理,沿用管理员会话、CSRF 和来源检查。普通网页进程仍无权写入 /etc。配置变更记录到任务管理审计表,同时触发一次硬件采集;页面每 10 秒刷新。
配置变更不会删除历史告警。旧缺卡和旧 UUID 告警随采集恢复保留在历史中,不应再作为当前故障显示。
每天 00:00 关机、06:00 开机
页面“定时任务”中使用名称“夜间节电:00:00 关机,06:00 开机”。执行周期为北京时间每天 00:00,命令为:
/usr/bin/python3 /opt/hardware-dashboard/scripts/night-power-cycle.py
脚本先用 rtcwake --utc --mode no 设置当天北京时间 06:00 的 RTC 唤醒,并回读 /sys/class/rtc/rtc0/wakealarm 核对时间。确认成功后调用 systemctl --no-block poweroff 正常关机。服务器的硬件时钟采用 UTC;不要求存在 /etc/adjtime。
脚本仅允许在北京时间 00:00 至 00:04 执行关机,避免白天点击“执行一次”时意外关机。若缺少 RTC 接口、设置闹钟失败或回读时间不符,本轮任务报错并保持开机。每天的任务均重新设置闹钟。系统定时器使用 Persistent=false,开机后不会补执行错过的关机任务。
仅检查环境和下次唤醒时间:
/usr/bin/python3 /opt/hardware-dashboard/scripts/night-power-cycle.py --check
这个检查不设置闹钟,也不执行关机。真正开机由主板完成,需要 BIOS 支持并启用关机状态 RTC 唤醒,且电源持续接通。00:00 正在运行的计算任务会中断;关机期间无法访问监控网页。RTC 闹钟设置成功不能证明主板一定能从关机状态唤醒,完整效果应在首次夜间周期后确认。
需要全天运行时,在页面停用这项计划。停用会取消后续关机调度,已设置的 RTC 闹钟仍可能保留。新增任务的“夜间节电”模板默认停用;如已有启用的同名任务,应编辑已有任务,避免重复添加。
本次在 192.168.1.37 已创建并启用一项夜间节电任务。首次关机计划为北京时间 2026-11-10 00:00,RTC 闹钟已设置并回读确认为 2026-11-10 06:00。未在部署时执行实际关机。原代码、原显卡配置和任务数据库的备份位于 /root/hardware-dashboard-backups/20261109-183339/。
新增文件与验证
scripts/night-power-cycle.py:RTC 设置、时间回读、关机及只读检查。tests/test_power_cycle.py:验证时区、跨日、白天禁止关机、闹钟失败或不匹配时不关机。tests/test_tasks.py:增加显卡数量输入校验、登录与 CSRF、其他配置保留及关机任务识别检查。
技术栈仍为 Python 标准库、HTML、CSS、原生 JavaScript、SQLite 和 systemd;RTC 唤醒使用系统已有的 util-linux rtcwake。部署时需同步新增的 scripts/ 目录,无需安装前端构建工具或第三方 Python 包。
本次本地和服务器端均通过 22 项自动化测试,前端脚本语法检查通过。实际网页已验证单卡显示 1/1、无缺卡告警、仅显示一张显卡卡片;390 像素手机视口无横向溢出。登录后保存 1/2 张显卡及夜间模板填写流程使用浏览器模拟接口验证,没有执行真实关机。RTC 闹钟已在真实设备上设置并回读,完整关机唤醒周期尚待首次计划执行后验证。