Files
ppgo_job/README.md
T
2026-07-10 11:28:16 +08:00

403 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
PPGo_Job 定时任务管理系统
====
一款轻量级定时任务管理系统,基于 **GoFrame v2** 重构。支持 **本机执行****SSH 远程执行**,部署简单,资源消耗少。
## 技术栈
- **后端框架:** GoFrame v2
- **数据库:** SQLite(纯 Go 驱动 `modernc.org/sqlite`,无需 CGO
- **定时任务:** GoFrame `gcron`
- **前端:** Vue 3 + Element Plus + TypeScript`frontend/` 目录)
- **旧前端(兼容):** LayUI 模板(`resource/template/`
- **远程执行:** SSH`golang.org/x/crypto/ssh`
## 快速开始
```bash
# 方式一:一键构建(前端 + 后端)
build_frontend.cmd
# 方式二:分步构建
# 1. 构建前端(首次或修改前端后需要)
cd frontend
npm install
npm run build
cd ..
# 2. 编译(纯 Go,不需要 gcc/MinGW
CGO_ENABLED=0 go build -o ppgo_job.exe .
# 3. 运行
./ppgo_job.exe
```
> 首次启动自动在 `./data/ppgo_job.db` 创建 SQLite 数据库、表和默认管理员。
**访问地址:** http://localhost:8082
**新前端:** http://localhost:8082/app/Vue 3 + Element Plus
**旧前端:** http://localhost:8082/LayUI,兼容保留)
**默认账号:** admin / **密码:** 123456
## 运行测试
```bash
# 运行所有测试
CGO_ENABLED=0 go test -count=1 ./...
# 运行单元测试(libs、consts、dao,无需启动服务器)
CGO_ENABLED=0 go test -count=1 ./libs/ ./consts/ ./dao/
# 运行集成测试(自动启动测试服务器,端口 18082)
CGO_ENABLED=0 go test -count=1 -timeout=120s -run "TestLogin|TestAuth|TestHome|TestTask|TestServer|TestGroup|TestBan|TestTemplate|TestStatic|TestDatabase|TestCORS" .
# 运行特定包测试
CGO_ENABLED=0 go test -v -count=1 ./libs/
```
> 集成测试覆盖登录、认证拦截、CRUD 操作、模板渲染、静态文件、CORS 头、数据库种子数据等功能。
> 测试使用独立的端口 `:18082`,不会干扰正在运行的开发实例。
---
## 📖 使用指南
### 1. 登录
打开浏览器访问 `http://localhost:8082`,输入默认账号 `admin` / `123456` 登录。
> 💡 如果访问时遇到"重定向次数过多",清除浏览器 Cookie 后刷新即可。
---
### 2. 首页仪表盘
登录后进入系统首页,展示:
- **任务概览** — 总任务数、运行中、待审核
- **近期执行统计** — 过去 7 天的成功/失败/超时柱状图
- **即将执行的任务** — 最近将要触发的定时任务
- **系统信息** — 运行时间、内存使用、goroutine 数量
---
### 3. 任务管理
#### 3.1 新增任务
左侧菜单「任务管理 → 任务列表」→ 点击「新增」按钮。
必填字段:
| 字段 | 说明 | 示例 |
|------|------|------|
| 任务名称 | 有意义的名称 | `数据库备份` |
| Cron 表达式 | **6 段格式(含秒)** | `0 0 3 * * *`(每天凌晨 3 点) |
| 执行命令 | 要执行的 shell 命令 | `mysqldump -u root db1 > /backup.sql` |
| 超时时间 | 超时后自动终止(秒) | `300`5 分钟) |
> ⚠️ **Cron 表达式注意事项:**
> 本项目使用 GoFrame `gcron`Cron 表达式为 **6 段格式**(比标准多一位秒):
>
> ```
> 秒 分 时 日 月 周
> ```
>
> 常用示例:
> - `0 */5 * * * *` — 每 5 分钟
> - `0 0 3 * * *` — 每天凌晨 3 点
> - `0 30 9 * * 1-5` — 工作日 9:30
> - `0 0 0 1 * *` — 每月 1 号零点
>
> 如果误填了标准 5 段表达式,系统会提示 `invalid pattern` 错误。
可选字段:
- **任务分组** — 归类管理
- **执行服务器** — 选择远程服务器(留空 = 本机执行)
- **执行方式** — 同时执行(所有服务器一起跑) / 轮询执行(逐台跑)
- **允许并发** — 默认不允许(上一个未执行完,下一个不会触发)
- **失败通知** — 勾选后可选择通知模板和接收人
#### 3.2 任务列表
列表展示了所有任务,支持:
- **按状态筛选** — 下拉框选择运行中/已暂停/待审核/审核失败
- **按分组筛选** — 下拉框选择任务分组
- **按名称搜索** — 输入关键字后点查询
- **表头排序** — 点击 ID 列头切换正序/倒序
- **表格操作按钮:**
| 按钮 | 功能 |
|------|------|
| 🔍 详细 | 查看任务完整信息 |
| ✏️ 编辑 | 修改任务参数 |
| ▶️ 启动 | 将暂停的任务加入调度 |
| ⏸️ 暂停 | 从调度中移除(暂不执行) |
| ▶️ 测试 | **立即执行一次**(不依赖 Cron 触发) |
| 📋 日志 | 查看该任务的执行记录 |
| 📝 复制 | 基于现有任务创建新任务 |
| 🗑️ 删除 | 软删除(可在数据库恢复) |
#### 3.3 任务审核
超级管理员 `admin` 创建的任务自动进入暂停状态;普通账号创建的任务进入「待审核」状态,需要管理员在「任务管理 → 任务审核」中通过后才能启动。
---
### 4. 服务器管理
#### 4.1 新增服务器
「服务器管理 → 服务器列表」→ 点击「新增」。
| 字段 | 说明 | 示例 |
|------|------|------|
| 服务器名称 | 标识名称 | `Web 服务器 01` |
| 连接方式 | SSH / Telnet / Agent | SSH |
| IP 地址 | 连接 IP | `192.168.1.100` |
| 端口 | SSH 默认 22 | `22` |
| 账号 | 登录用户名 | `root` |
| 密码/密钥 | 密码或私钥内容 | — |
> SSH 远程执行已实现,支持密码和密钥认证。创建任务时选择配置好的服务器即可远程执行。
#### 4.2 资源分组
将服务器归类管理。多个服务器可以属于同一个资源组,方便在创建任务时批量选择。
---
### 5. 系统设置
#### 5.1 任务分组
对任务进行分类,例如:`数据备份``日志清理``监控脚本`
#### 5.2 禁用命令
设置禁止执行的关键词。创建/编辑任务时,如果命令包含禁用词(如 `rm -rf`),系统会拒绝保存。
#### 5.3 通知模板
配置任务执行失败时的通知内容。支持变量占位符:`{{task_name}}``{{status}}`
> 邮件通知已实现(`net/smtp`),任务失败时自动发送邮件到通知人。
---
### 6. 执行日志
「日志管理 → 执行日志」查看所有任务的执行记录。
| 字段 | 说明 |
|------|------|
| 状态 | ✅ 成功 / ❌ 失败 / ⏰ 超时 |
| 耗时 | 执行耗时(毫秒) |
| 执行时间 | 触发时间 |
| 输出 | 命令的标准输出 |
| 错误 | 错误信息(如果有) |
支持按任务 ID 筛选、分页浏览、查看详情和删除。
---
### 7. 权限管理
#### 7.1 权限因子
系统内置的菜单和功能权限,支持新增/编辑/删除。每个权限对应一个侧边栏菜单项。
权限结构为两级:
- **一级菜单** — 如「任务管理」「服务器管理」
- **二级菜单** — 如「任务列表」「任务审核」
#### 7.2 角色管理
创建角色并绑定权限,支持数据权限控制(限制可查看的服务器组和任务组)。
例如创建一个「运维人员」角色,只赋予任务管理和日志查看权限。
#### 7.3 管理员管理
创建系统用户,可关联角色。新增的管理员默认密码 `123456`
> `admin` 是超级管理员,**不能被禁用**,拥有全部权限。
---
### 8. 个人资料
右上角用户头像 → 可修改个人资料(姓名、电话、邮箱、钉钉/微信等)及修改密码。
---
## 注意事项
### ⚡ Cron 表达式格式
本项目使用 **6 段格式**(含秒),不要使用标准 5 段格式:
```
✅ 正确: 0 0 3 * * * (每天凌晨 3 点)
❌ 错误: 0 3 * * * (缺少秒字段 → 报错)
✅ 正确: 0 */5 * * * * (每 5 分钟)
```
### 🔒 端口冲突
如果启动提示 `bind: Only one usage of each socket address`,说明端口 8082 已被占用:
```bash
# 查看谁占了端口
netstat -ano | findstr 8082
# 杀掉进程(PID 替换为实际值)
taskkill //PID 进程号 //F
# 或者修改 config.yml 换个端口
```
### 💾 数据库
SQLite 数据库文件在 `./data/ppgo_job.db`,直接复制即可备份。如需重置,删除该文件后重启服务即可自动重建。
---
## 项目结构
```
├── main.go # 入口
├── config.yml # 配置文件
├── boot/ # 启动初始化
│ ├── db.go # 数据库目录初始化
│ ├── router.go # 路由注册 + 路由表
│ ├── tplfunc.go # 模板函数(urlfor/date/substr
│ └── init.go # 自动建表 + 种子数据 + 加载调度任务
├── frontend/ # Vue 3 前端工程
│ ├── src/ # 源码(api/router/stores/views/layout
│ ├── dist/ # 构建产物(Go 静态文件服务)
│ ├── vite.config.ts
│ └── package.json
├── controller/ # HTTP 控制器
│ ├── base.go # display/ajaxMsg/ajaxList 辅助函数
│ ├── response.go # 统一 JSON 响应格式
│ ├── api.go # Vue 前端专用 API 端点
│ ├── login.go # 登录/登出(Cookie+JWT 双认证)
│ ├── home.go # 首页仪表盘
│ ├── task.go # 任务/服务器/分组/日志/CRUD
│ ├── admin.go # 服务器/分组/禁用命令/通知模板 CRUD
│ ├── system.go # 权限因子/角色/管理员/个人资料 CRUD
│ └── spa.go # SPA 静态文件服务
├── service/
│ └── scheduler/ # 任务调度 + 执行引擎
│ ├── scheduler.go # gcron 调度管理
│ ├── task_runner.go # 命令执行器(本地/远程)
│ ├── ssh.go # SSH 远程连接器
│ └── notify.go # 邮件通知实现
├── dao/ # 数据访问层
├── model/entity/ # 数据库实体(含字段常量)
├── middleware/ # 认证中间件(Cookie + JWT 双认证)
├── libs/ # 工具函数(密码哈希/JWT/加密)
├── consts/ # 常量定义
└── resource/
├── template/ # LayUI 模板(旧前端)
└── static/ # JS/CSS/字体(旧前端)
```
## 配置文件(`config.yml`
```yaml
server:
address: ":8082" # 监听端口
name: "ppgo_job"
logStdout: true # 日志输出到控制台
database:
default:
type: sqlite # 数据库类型(仅支持 sqlite
name: "./data/ppgo_job.db"
jobs:
pool: 1000 # 任务并发池大小
site:
name: "定时任务管理器" # 站点标题
```
## API 接口
### 新前端 API`/api/*`JWT 认证)
| 接口 | 方法 | 说明 |
|------|------|------|
| `/api/login_in` | POST | 登录(返回 JWT token |
| `/api/user_info` | GET | 当前用户信息 + 菜单树 |
| `/api/dashboard` | GET | 仪表盘统计数据(含 7 天图表) |
| `/api/task/table` | GET | 任务列表(支持 status/group_id/task_name 筛选,field/order 排序) |
| `/api/task/save` | POST | 新增/编辑任务 |
| `/api/task/start` | POST | 启动任务 |
| `/api/task/pause` | POST | 暂停任务 |
| `/api/task/del` | POST | 删除任务 |
| `/api/task/run` | POST | 立即执行 |
| `/api/task/audit` | POST | 审核通过 |
| `/api/task/nopass` | POST | 审核不通过 |
| `/api/task/add_data` | GET | 新增任务的关联数据(分组/服务器/通知人) |
| `/api/task/edit_data` | GET | 编辑任务的数据 |
| `/api/task/detail_data` | GET | 任务详情 |
| `/api/server/table` | GET | 服务器列表 |
| `/api/server/save` | POST | 新增/编辑服务器 |
| `/api/server/del` | POST | 删除服务器 |
| `/api/group/table` | GET | 任务分组列表 |
| `/api/server_group/table` | GET | 资源分组列表 |
| `/api/ban/table` | GET | 禁用命令列表 |
| `/api/notify_tpl/table` | GET | 通知模板列表 |
| `/api/auth/nodes` | GET | 权限树 |
| `/api/role/table` | GET | 角色列表 |
| `/api/admin/table` | GET | 管理员列表 |
| `/api/task_log/table` | GET | 执行日志列表(支持 status/task_id 筛选) |
| `/api/profile` | GET | 个人资料 |
| `/api/user/save` | POST | 修改个人资料 |
### 旧前端 APICookie 认证,兼容保留)
| 接口 | 方法 | 说明 |
|------|------|------|
| `/login_in` | POST | 登录 |
| `/task/ajax_save` | POST | 新增/编辑任务 |
| `/task/ajax_del` | POST | 删除任务 |
| ... | ... | 其他 `ajax_*` 端点同旧版 |
完整路由见 `boot/router.go`
## 编译部署
```bash
# 本地运行(含前端构建)
build_frontend.cmd
# 或分步运行
cd frontend && npm install && npm run build && cd ..
CGO_ENABLED=0 go build -o ppgo_job.exe . && ./ppgo_job.exe
# 仅编译后端
CGO_ENABLED=0 go build -o ppgo_job.exe .
# Linux 交叉编译
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ppgo_job .
# Windows 交叉编译
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o ppgo_job.exe .
# Mac 交叉编译
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o ppgo_job .
```
## 已知限制
- **Telnet/Agent 远程执行** — 已实现 SSHTelnet 和 Agent 模式尚未支持
- **钉钉/微信通知** — 已实现邮件通知,钉钉和微信待补充
- **Agent API** — 远程 Agent 注册和管理暂未实现
- **旧前端兼容** — LayUI 前端保留但不再维护,新功能仅添加到 Vue 前端
## License
MIT