Files
sproutclaw-cron/cronctl.py
shumengya 6c2db2dfa3 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 后端 + 文档式响应式前端
2026-06-24 16:19:53 +08:00

110 lines
3.2 KiB
Python
Executable File
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.
#!/usr/bin/env python3
"""shumengya cron 任务开关与运行管理。"""
from __future__ import annotations
import argparse
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent / "lib"))
from shumengya_cron.manager import (
cron_root,
get_context,
iter_task_ids,
migrate_legacy_disabled_layout,
run_task,
set_task_state,
sync_cron_d,
)
from shumengya_cron.runner import task_enabled_text, task_is_enabled
CRON_ROOT = cron_root()
def _resolve_task_ids(values: list[str]) -> list[str]:
if not values:
return iter_task_ids(CRON_ROOT)
if len(values) == 1 and values[0] == "all":
return iter_task_ids(CRON_ROOT)
return values
def _print_status(task_id: str) -> None:
ctx = get_context(task_id, CRON_ROOT)
print(f"{ctx.task_id}: {task_enabled_text(ctx)}")
def _set_state(task_id: str, enabled: bool) -> None:
_info, message = set_task_state(task_id, enabled, CRON_ROOT)
print(f"{task_id}: {'开启' if enabled else '关闭'}")
if message:
print(f"{message}")
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(
prog="cronctl.py",
description="管理 /shumengya/project/agent/sproutclaw-cron 下每个定时任务的开关状态,或手动执行任务。",
)
parser.add_argument(
"action",
nargs="?",
default="status",
choices=["status", "enable", "disable", "toggle", "on", "off", "run", "sync-cron"],
help="status / enable / disable / toggle / run / sync-cron",
)
parser.add_argument("tasks", nargs="*", help="任务名status 时默认列出全部;也可传 all")
args = parser.parse_args(argv)
migrate_legacy_disabled_layout(CRON_ROOT)
action = args.action
if action == "on":
action = "enable"
elif action == "off":
action = "disable"
task_ids = _resolve_task_ids(list(args.tasks))
if not task_ids:
print("未找到可管理的任务。", file=sys.stderr)
return 1
if action in {"enable", "disable", "toggle", "run", "sync-cron"} and not args.tasks:
print("请至少指定一个任务名,或传 all。", file=sys.stderr)
return 1
rc = 0
for task_id in task_ids:
try:
if action == "run":
task_rc = run_task(task_id, CRON_ROOT)
print(f"{task_id} (exit={task_rc})")
if task_rc != 0:
rc = task_rc
continue
if action == "status":
_print_status(task_id)
elif action == "sync-cron":
ctx = get_context(task_id, CRON_ROOT)
message = sync_cron_d(ctx, task_is_enabled(ctx))
if message:
print(f"{message}")
elif action == "enable":
_set_state(task_id, True)
elif action == "disable":
_set_state(task_id, False)
else:
_set_state(task_id, not task_is_enabled(get_context(task_id, CRON_ROOT)))
except FileNotFoundError as e:
print(str(e), file=sys.stderr)
rc = 1
return rc
if __name__ == "__main__":
raise SystemExit(main())