feat: init sproutclaw-cron 定时任务管理框架
- 每任务一目录结构,统一开关与日志 - cronctl CLI:enable/disable/toggle/status/run/sync-cron - 公共库 lib/shumengya_cron:runner/manager/notify/ssh - _template 示例任务(hello world + 复制模板) - webui 管理面板:FastAPI 后端 + 文档式响应式前端
This commit is contained in:
49
_template/README.md
Normal file
49
_template/README.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# 定时任务模板 / 示例任务
|
||||
|
||||
`_template` 本身是可管理的真实任务:每天 08:00 输出 `hello world`。
|
||||
新建任务时复制本目录,改任务名与业务逻辑即可。
|
||||
|
||||
## 新建步骤
|
||||
|
||||
```bash
|
||||
TASK_ID="smallmengya-my-new-task"
|
||||
CRON_ROOT="/shumengya/project/agent/sproutclaw-cron"
|
||||
|
||||
cp -a "$CRON_ROOT/_template" "$CRON_ROOT/$TASK_ID"
|
||||
sed -i "s/_template/$TASK_ID/g" "$CRON_ROOT/$TASK_ID/schedule.cron"
|
||||
chmod +x "$CRON_ROOT/$TASK_ID/switch.sh"
|
||||
|
||||
# 编辑 run.py,替换 hello world 为实际业务逻辑
|
||||
# 编辑 schedule.cron,调整 cron 表达式与注释
|
||||
|
||||
python3 "$CRON_ROOT/cronctl.py" status "$TASK_ID"
|
||||
python3 "$CRON_ROOT/cronctl.py" run "$TASK_ID" # 手动试跑
|
||||
python3 "$CRON_ROOT/cronctl.py" enable "$TASK_ID" # 开启并同步 /etc/cron.d/
|
||||
```
|
||||
|
||||
## 必须文件
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `run.py` | 任务入口,导出 `run(ctx) -> int` |
|
||||
| `schedule.cron` | 系统 cron 配置,cron 行须调用 `cronctl.py run <task-id>` |
|
||||
| `switch.sh` | 可选,代理 `cronctl` 开关 |
|
||||
|
||||
## run.py 约定
|
||||
|
||||
1. 入口第一行检查 `task_is_disabled(ctx)`,关闭时直接 `return 0`
|
||||
2. 使用 `task_logging(ctx)` 写日志到 `logs/<task-id>.log`
|
||||
3. 使用 `acquire_cron_lock(ctx.lock_file, log=log)` 防止并发重入
|
||||
4. 业务逻辑写在 `log("start")` 与 `log("end")` 之间
|
||||
5. 需要汇总通知时使用 `shumengya_cron.notify.send_task_summary`
|
||||
|
||||
## schedule.cron 约定
|
||||
|
||||
- 保留 `SHELL` / `PATH` / `HOME` / `CRON_MAIL_ENABLED` 头部
|
||||
- 用 `#` 注释写一句任务说明(WebUI 会读取展示)
|
||||
- cron 行格式:`分 时 日 月 周 root python3 .../cronctl.py run <task-id> >/dev/null 2>&1`
|
||||
- 本模板默认 **每天 08:00**(`0 8 * * *`)
|
||||
|
||||
## 任务 ID 命名
|
||||
|
||||
`<主机名>-<功能描述>`,例如 `smallmengya-gitea-repo-sync`。
|
||||
46
_template/run.py
Normal file
46
_template/run.py
Normal file
@@ -0,0 +1,46 @@
|
||||
"""
|
||||
Hello World 示例任务:每天 08:00 输出一句 hello world。
|
||||
|
||||
新建任务时复制整个 _template/ 目录为 <task-id>/,更新 schedule.cron 中的
|
||||
任务名,再替换下方业务逻辑。命名约定:<主机名>-<功能描述>。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys as _sys, pathlib as _pl
|
||||
_sys.path.insert(0, str(_pl.Path(__file__).resolve().parents[1] / "lib"))
|
||||
del _sys, _pl
|
||||
|
||||
from shumengya_cron.runner import (
|
||||
TaskContext,
|
||||
acquire_cron_lock,
|
||||
task_is_disabled,
|
||||
task_logging,
|
||||
)
|
||||
|
||||
|
||||
def run(ctx: TaskContext) -> int:
|
||||
if task_is_disabled(ctx):
|
||||
return 0
|
||||
|
||||
with task_logging(ctx) as log:
|
||||
with acquire_cron_lock(ctx.lock_file, log=log) as locked:
|
||||
if not locked:
|
||||
return 0
|
||||
|
||||
log("start")
|
||||
log("hello world")
|
||||
log("end")
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def main() -> int:
|
||||
import pathlib
|
||||
task_id = pathlib.Path(__file__).parent.name
|
||||
ctx = TaskContext.from_task_id(task_id)
|
||||
return run(ctx)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
9
_template/schedule.cron
Normal file
9
_template/schedule.cron
Normal file
@@ -0,0 +1,9 @@
|
||||
SHELL=/bin/bash
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
HOME=/root
|
||||
CRON_MAIL_ENABLED=1
|
||||
|
||||
# 每天 08:00 输出 hello world(示例任务,复制本目录创建新任务)
|
||||
# 将本文件复制到 /etc/cron.d/_template 即可生效(cronctl enable 会自动同步)
|
||||
# 开关:python3 /shumengya/project/agent/sproutclaw-cron/cronctl.py enable|disable|toggle _template
|
||||
0 8 * * * root /usr/bin/python3 /shumengya/project/agent/sproutclaw-cron/cronctl.py run _template >/dev/null 2>&1
|
||||
8
_template/switch.sh
Normal file
8
_template/switch.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
task_id="$(basename "$(dirname "$0")")"
|
||||
action="${1:-toggle}"
|
||||
shift || true
|
||||
|
||||
exec python3 /shumengya/project/agent/sproutclaw-cron/cronctl.py "$action" "$task_id" "$@"
|
||||
Reference in New Issue
Block a user