# ql
**Repository Path**: deshuofa/ql
## Basic Information
- **Project Name**: ql
- **Description**: php麒麟面板(参考青龙面板)
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-10-27
- **Last Updated**: 2026-10-27
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# ql — PHP 定时任务调度面板
> 一个轻量级的「青龙类」任务调度面板:由系统 Cron 或外部定时服务驱动调度器与执行器,
> 支持多 Cron 表达式、执行队列、失败重试、日志查看、后台管理与 API 调用。
> 运行环境:PHP 8.3 + MySQL 5.7+ / MariaDB 10.2+,已在虚拟主机环境验证可用。
## 简介
ql 使用 PHP + MySQL 实现任务调度与执行,整体分为三层:
- **调度器 `scheduler.php`**:由系统 Cron 或外部定时服务每分钟触发,判断任务是否到期,写入执行队列 `task_queue`,并定期清理日志与历史记录。
- **执行器 `executor.php`**:由系统 Cron 或外部定时服务每分钟触发,从队列取 `pending` 任务,运行 `scripts/` 下的脚本,写日志、按失败次数重试。
- **后台 `admin/` 与接口 `api/`**:任务增删改查、脚本管理、环境变量、日志查看、Token 管理等。
调度器与执行器均带文件锁(`data/*.lock`),并通过 API Token 鉴权,避免重复运行和未授权访问。
## 功能特性
- 多 Cron 表达式:单个任务支持配置多个 Cron(`tasks.cron_exprs` 存 JSON 数组)
- 执行队列:`task_queue` 记录 pending/running/success/failed,带 `scheduled_at` 与重试计数
- 失败重试:`config.php` 中 `max_retry` 控制最大重试次数
- 并发控制:调度器/执行器文件锁,执行器分批取任务(`executor_batch_size`)
- 后台管理:任务、脚本、环境变量、日志、设置、Token
- API 接口:`api/` 提供任务、脚本、日志、Token 等接口,使用 API Token 鉴权
- 防暴力破解:登录失败次数限制与锁定(`login_max_fail` / `login_lock_seconds`)
- 时区与调试:`timezone` 默认 `Asia/Shanghai`,`debug` 开关
- 定时触发灵活:支持主机 Cron、curl/wget 调用、cron-job.org 等外部定时服务
## 环境要求
- PHP 8.3(需 `pdo_mysql`、`json`、`curl` 扩展)
- MySQL 5.7+ / MariaDB 10.2+,字符集 `utf8mb4`
- 支持 Cron 定时任务、允许触发 PHP 的虚拟主机或服务器;或使用 cron-job.org 等外部定时服务
- 可写目录:`data/`(锁文件)、日志目录
## 目录结构
```
ql/
├── admin/ # 后台页面(登录、任务、脚本、日志、设置等)
├── api/ # 接口(任务/脚本/环境/日志/Token 等)
├── lib/ # 公共类库
│ ├── Db.php # 数据库单例
│ ├── Cron.php # Cron 表达式解析
│ ├── Auth.php # API Token 鉴权
│ ├── AdminAuth.php # 后台登录鉴权
│ ├── TaskRunner.php # 任务执行逻辑
│ ├── Setting.php # 全局配置读写
│ ├── Env.php # 环境变量
│ ├── HttpClient.php # HTTP 客户端
│ ├── QingLongApi.php # 青龙 API 封装
│ ├── SupabaseAuth.php# Supabase 鉴权
│ └── Response.php # 统一响应
├── scripts/ # 被调度的脚本(当前含 backup.php、scripts.json)
├── config.php # 全局配置
├── scheduler.php # 调度器
├── executor.php # 执行器
├── install.sql # 数据库初始化
├── LICENSE # MIT 许可证
└── README.md
```
## 快速开始
### 1. 获取代码
```bash
git clone https://gitee.com/deshuofa/ql.git
cd ql
mkdir -p data
```
### 2. 初始化数据库
```bash
mysql -u <用户> -p <数据库名> < install.sql
```
### 3. 修改配置
编辑 `config.php`,填写数据库连接等信息:
```php
'db' => [
'host' => 'localhost',
'port' => 3306,
'name' => '<数据库名>',
'user' => '<用户名>',
'pass' => '<密码>',
'charset' => 'utf8mb4',
],
```
其他可调项:
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| `max_execution_time` | 250 | 执行器总时间上限(秒) |
| `executor_batch_size` | 5 | 执行器一次从队列取几条 |
| `max_retry` | 2 | 失败最大重试次数 |
| `admin_token_ttl` | 86400 | 后台 Token 有效期(秒) |
| `login_max_fail` | 5 | 登录最大失败次数 |
| `login_lock_seconds` | 900 | 登录锁定秒数 |
| `timezone` | `Asia/Shanghai` | 时区 |
| `debug` | `false` | 调试模式,生产环境设为 false |
### 4. 部署 Web
将项目放到 Web 根目录,或配置虚拟主机指向项目根目录,访问 `admin/` 进入后台。
### 5. 配置定时触发
调度器与执行器需要每分钟触发一次。根据环境选择以下任一方式(详见「虚拟主机部署」)。
## 虚拟主机部署(已验证)
本项目已在虚拟主机环境完成部署验证,可直接用于支持 Cron 的虚拟主机,或配合 cron-job.org 等外部定时服务使用。
### 部署前提
- PHP 8.3,启用 `pdo_mysql`、`json`、`curl`
- 可创建 MySQL 数据库并导入 `install.sql`
- 主机提供 Cron / 计划任务,或使用 cron-job.org 等外部定时服务
- `data/` 与日志目录可写
### 部署步骤
1. 上传代码到 Web 目录,创建 `data/` 并设可写
2. 导入 `install.sql`,修改 `config.php` 数据库配置
3. 访问 `admin/` 登录后台,立即修改密码、替换占位 Token
4. 配置定时触发(见下)
### 定时触发方式
**方式 A:主机 Cron + CLI 执行(推荐)**
```bash
* * * * * /usr/bin/php /home/<用户>/public_html/ql/scheduler.php >> /home/<用户>/ql_data/scheduler.log 2>&1
* * * * * /usr/bin/php /home/<用户>/public_html/ql/executor.php >> /home/<用户>/ql_data/executor.log 2>&1
```
**方式 B:主机 Cron + URL 调用(无 CLI 权限时)**
```bash
* * * * * curl -s "https://<域名>/ql/scheduler.php?token=<调度器Token>" > /dev/null 2>&1
* * * * * curl -s "https://<域名>/ql/executor.php?token=<执行器Token>" > /dev/null 2>&1
```
**方式 C:cron-job.org(无主机 Cron 权限时)**
使用 [cron-job.org](https://console.cron-job.org/) 在线服务定时触发调度器与执行器:
1. 注册并登录 console.cron-job.org
2. 创建两个 Cron Job,URL 分别填:
- `https://<域名>/ql/scheduler.php?token=<调度器Token>`
- `https://<域名>/ql/executor.php?token=<执行器Token>`
3. 执行间隔设为 **每分钟**(免费版支持最短 1 分钟)
4. 在 Advanced 设置中按需添加 Header(Token 传递方式以 `lib/Auth.php` 为准)
> **重要限制**:cron-job.org 免费版单次请求超时 **30 秒**,超时后会断开连接。本项目的执行器默认 `max_execution_time` 为 250 秒,若任务执行时间可能超过 30 秒,需注意:
> - 将长任务拆分或优化到 30 秒内完成
> - 或将 `config.php` 中 `max_execution_time` 调低至 25 秒左右,确保执行器在 cron-job.org 超时前正常退出
> - 或升级 cron-job.org 会员(超时延长至 5 分钟)
> 调度器/执行器均带文件锁,重复触发会被跳过;若通过 Web/FPM 调用,脚本会先 `fastcgi_finish_request()` 再后台执行,CLI 下不受影响。
### 已验证环境
- 虚拟主机 + PHP 8.3 + MySQL,定时触发调度器与执行器,任务调度与执行正常
### 虚拟主机注意事项
- **Cron 频率**:部分主机最短间隔较长,会影响调度精度,按主机限制调整即可
- **cron-job.org 超时**:免费版 30 秒断连,执行器需确保单次运行在 30 秒内,或调整 `max_execution_time`
- **执行时间限制**:Web 方式受 `max_execution_time` 与 FPM 超时限制,长任务建议 CLI
- **文件锁**:确认主机文件系统支持 `flock`;NFS 共享存储可能不可靠
- **路径**:cron 中 `php` 用绝对路径(`which php` 查看)
- **日志目录**:确保 `data/` 与任务 `log_dir` 可写
- **禁止外部访问**:`data/`、`config.php`、`install.sql` 应通过 `.htaccess` 或主机规则禁止直接访问
### 加固示例(Apache `.htaccess`)
放在项目根目录:
```apache
Require all denied
RewriteRule ^data/ - [F,L]
```
Nginx 主机:
```nginx
location ~ ^/(data|config\.php|install\.sql) { deny all; }
```
## 后台与登录
- 入口:`admin/index.php`
- 初始密码:`admin123`(`install.sql` 中写入 `settings.admin_password` 的 bcrypt 哈希)
- **部署后请立即在后台修改密码**
## API Token
`install.sql` 预置了 3 个占位 Token(`REPLACE_WITH_RANDOM_TOKEN_*`,分别用于 D服务、调度器 Cron、执行器 Cron),并带有 `scopes`(允许的入口,逗号分隔,空表示全部)与 `status` 字段。
- **部署后请立即在后台重新生成或替换为随机值**
- 调度器/执行器通过 `Auth::verify($db, 'scheduler'/'executor')` 校验 Token
- API 调用需携带对应 Token(具体头/参数以 `lib/Auth.php` 实现为准)
## 数据表
| 表 | 说明 |
|----|------|
| `tasks` | 任务定义(名称、脚本路径、参数 JSON、多个 Cron、日志目录、状态、上次调度时间) |
| `task_queue` | 执行队列(任务、计划时间、状态、开始/结束时间、日志路径、重试次数、错误摘要) |
| `settings` | 全局配置(后台密码、登录失败计数、锁定截止时间等) |
| `admin_tokens` | 后台临时 Token(有效期、最后使用时间) |
| `api_tokens` | 外部服务 API Token(用途、scopes、状态、最后使用时间) |
## 脚本管理
- 脚本放在 `scripts/` 目录,`tasks.script_file` 存相对 `scripts/` 的路径
- `scripts/scripts.json` 维护脚本元信息(以后台/接口实际读取为准)
- 执行器通过 `TaskRunner` 运行脚本并写日志到任务的 `log_dir`
## PHP 8.3 兼容性
本项目在 PHP 8.3 下开发/运行。若从旧版本迁移,注意:
- PHP 8.2+ 弃用动态属性,类中请显式声明属性或加 `#[AllowDynamicProperties]`
- 弃用 `${var}` 字符串插值,请改用 `{$var}`
- 弃用 `utf8_encode` / `utf8_decode`,请改用 `mb_convert_encoding`
- 内置函数传 `null` 到非 nullable 参数会告警,注意判空
- 调度器/执行器在 CLI 下运行,`fastcgi_finish_request()` 已做 `function_exists` 判断,不影响 CLI 执行
## 常见问题
**Q: 任务没有被调度?**
A: 确认定时触发在跑 `scheduler.php`(主机 Cron 或 cron-job.org),`tasks.status = 1`,且 `cron_exprs` 与当前时间匹配。
**Q: 任务一直在 pending?**
A: 确认 `executor.php` 的定时触发在运行,且 `data/` 目录可写(锁文件)。
**Q: 数据库连接失败?**
A: 核对 `config.php` 的 `db` 配置,确认已执行 `install.sql`。
**Q: 后台登录被锁定?**
A: 达到 `login_max_fail` 次会锁定 `login_lock_seconds` 秒,可等待或清理 `settings` 中的 `login_lock_until`。
**Q: 虚拟主机 Cron 频率有限制怎么办?**
A: 本项目已在支持 Cron 的虚拟主机验证可用;若主机最短间隔较长,调度精度会受影响,按主机限制调整即可,或改用 cron-job.org。
**Q: 用 cron-job.org 触发执行器,任务执行到一半被中断?**
A: cron-job.org 免费版 30 秒超时断连。建议将 `max_execution_time` 设为 25 左右,或拆分任务,或升级 cron-job.org 会员。
**Q: 如何更新?**
A: `git pull`;如表结构有变更,按新的 `install.sql` 增量执行。
## 安全建议
- 立即修改后台初始密码,替换所有占位 API Token
- 生产环境将 `debug` 设为 `false`
- 限制 `admin/`、`api/` 访问来源,启用 HTTPS
- `config.php` 中的数据库密码注意文件权限
- 虚拟主机上用 `.htaccess` 或主机规则禁止访问 `data/`、`config.php`、`install.sql`
- 使用 cron-job.org 时,URL 中的 Token 会出现在第三方服务日志中,建议使用独立 Token 并定期轮换
## 许可证
本项目采用 [MIT License](LICENSE) 开源。
## 免责声明
本项目仅供学习与内部使用,请自行评估安全性与合规性,使用风险自负。