310 lines
19 KiB
Markdown
310 lines
19 KiB
Markdown
# 192.168.1.37 监控与定时任务技术说明
|
||
|
||
版本:v1.3,2026 年 11 月 9 日。新增显卡数量设置和夜间节电计划,详见第 12 节。
|
||
|
||
## 1. 访问与登录
|
||
|
||
设备监控页面:**[http://192.168.1.37:8090](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. 第一次添加任务
|
||
|
||
1. 刷新页面,打开“定时任务”,点击“登录管理”。
|
||
2. 使用交付文件中的 `admin` 与初始密码登录。
|
||
3. 点击“新增任务”,填写任务名称。
|
||
4. 选择执行方式,输入命令、脚本或服务器脚本路径。
|
||
5. 设置执行周期,点击“检查执行周期”核对下次时间。
|
||
6. 保持“保存后启用”不勾选,先保存为停用状态。
|
||
7. 如适合测试,点击“执行一次”,确认执行内容,查看执行日志。
|
||
8. 核对结果后,再启用计划。
|
||
|
||
保存任务本身不会立即执行脚本。新任务默认停用。退出登录、关闭网页或重启网页服务不会停止已经启用的系统计划。
|
||
|
||
### 常用模板
|
||
|
||
新增窗口提供:
|
||
|
||
- **显卡状态检查**:读取 `nvidia-smi`,结果保存在执行日志中。
|
||
- **服务器定时重启**:示例命令为 `systemctl reboot`,默认周期是每周日 03:00,默认停用。启用或立即执行前都会提示可能中断计算任务。
|
||
- **SSL 证书续签示例**:检查已有的 Certbot/acme.sh 工具并调用其续签入口。它不会安装工具、申请新域名或替用户配置证书。先确认现有续签配置,以及是否已经有其他自动续签任务;Web 服务的重新加载应按实际服务配置。
|
||
|
||
本次部署没有创建或启用实际的服务器重启任务和证书续签任务,也没有执行这两类操作。
|
||
|
||
## 4. 执行周期
|
||
|
||
所有日历时间按 **Asia/Shanghai,北京时间 UTC+8** 处理,页面显示服务器当前时间。
|
||
|
||
| 周期 | 规则 |
|
||
|---|---|
|
||
| 每天 | 指定时、分。 |
|
||
| 每周 | 可选择一个或多个星期及时间。 |
|
||
| 每月 | 选择 1 至 31 日和时间;当月不存在该日期时跳过。 |
|
||
| 每隔若干分钟/小时 | 启用后先等待指定间隔;每次执行结束后重新计时,避免长任务造成重叠。 |
|
||
| 指定日期,仅执行一次 | 选择未来的日期和时间,精确到分钟;至少晚于保存时刻 30 秒。 |
|
||
| 自定义 Cron | 标准五段:分、时、日、月、周。支持 `*`、逗号、范围、步长及常见英文月/星期名。 |
|
||
|
||
Cron 示例:
|
||
|
||
```text
|
||
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 面板](https://www.bt.cn/) 计划任务的组织方式:任务列表、执行周期、Shell 脚本、启停、手动执行和执行日志。本次功能自行编写,沿用已有监控页面的深色风格,没有安装宝塔,也没有复制其面板源码。
|
||
|
||
原监控布局仍参考:
|
||
|
||
- [Zabbix](https://github.com/zabbix/zabbix):设备总览和告警分级。
|
||
- [Netdata](https://github.com/netdata/netdata):实时指标展示。
|
||
- [Grafana](https://github.com/grafana/grafana):历史曲线、图例和时间范围。
|
||
|
||
| 部分 | 使用技术 |
|
||
|---|---|
|
||
| 监控与任务前端 | 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. 为什么要拆成两个服务
|
||
|
||
```mermaid
|
||
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. 常用维护命令
|
||
|
||
```bash
|
||
# 查看网页服务与任务服务
|
||
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 执行以下命令。新密码在交互输入,不放进命令行参数:
|
||
|
||
```bash
|
||
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`,命令为:
|
||
|
||
```bash
|
||
/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`,开机后不会补执行错过的关机任务。
|
||
|
||
仅检查环境和下次唤醒时间:
|
||
|
||
```bash
|
||
/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 闹钟已在真实设备上设置并回读,完整关机唤醒周期尚待首次计划执行后验证。
|