定时任务执行
下载地址
https://www.zhengdianxue.com/wp-content/uploads/skills/lexord-technology--schedule-runner.zip将提示词发送给你的 AI 安装该 skills
请根据 https://skillhub.cn/install/skillhub.md,安装 @lexord-technology/schedule-runner。【律令】(cron 解析生成 · schtasks 命令)定时任务与计划任务管家:cron 表达式解析/生成/校验,算下次执行时间,生成 Windows schtasks 命令,标注 OR 语义与时区陷阱,适用于定时执行与任务调度场景。
阅读全文 (展开查看完整说明)
概述
本地运行,零网络请求、免 API Key、不主动外发数据。
四项诚实承诺:① 算不出就说算不出,绝不编造数字;② 高危动作强制人工确认;③ 幂等断点,绝不重复副作用;④ 全程留痕可审计。
边界说明:本包脚本自身不联网、不外发;若你把内容贴进 AI 对话,内容是否离开本机由你所使用的客户端决定,不由本包决定。
<!– WB-CLAIM-BOUNDARY v1 –>
定时执行
运行方式
<!– WB-INVOKE-CONTRACT v1 –>
环境:Python 3.8+,仅标准库,无需安装任何依赖。
作用:定时执行:cron 表达式的解析/生成/校验,以及落地成 Windows 计划任务
命令(在技能目录下执行;<尖括号> 是你要替换的输入):
# 查看子命令帮助
python scripts/schedule_runner.py --help
# 按子命令执行(示例)
python scripts/schedule_runner.py parse <参数>子命令:
| 子命令 | 说明 |
|---|---|
parse | 解析 cron → 人类可读 + 字段展开 |
next | 算接下来 N 次执行时间 |
build | 从人话生成 cron 表达式 |
schtasks | 生成 Windows schtasks /Create 命令 |
lint | 定时坑位体检 |
fields | 字段取值范围速查 |
选项:
| 选项 | 说明 |
|---|
退出码:0 成功 / 2 输入错误 / 3 鉴权失败 / 4 环境或依赖失败 / 8 部分成功。
输出:产物写入执行目录,源文件不改动;先跑预览确认,再加 --execute 落盘。
相邻路线转交
本包只做自己职责范围内的事,遇到下列情形直接转给兄弟技能:
| 用户要做的事 | 转交给 | 转交话术 |
|---|---|---|
| 定时触发的是一批任务 | lexord-batch-runner | 「批量执行交给 lexord-batch-runner」 |
| 定时触发的是桌面流程 | lexord-rpa-flow | 「流程编排交给 lexord-rpa-flow」 |
| 定时任务失败要重试 | lexord-retry-guard | 「重试策略交给 lexord-retry-guard」 |
反向边界:只做 cron 解析、下次执行时间计算与命令生成,不保证任务本身成功。时区与 OR 语义陷阱必须显式标注。
你是一个调度表达式翻译官:把 */15 * * * * 翻译成人话,也把人话翻译成 cron,并主动指出这类表达式里最反直觉的坑。核心原则:描述用不带歧义的人话、搬不过去的条件如实告警不假装等价、时间计算穷举验证而不是心算。
环境准备
纯 Python 标准库,无第三方依赖。
python scripts/schedule_runner.py <子命令> [参数]子命令
| 子命令 | 作用 |
|---|---|
parse | 解析 cron → 人类可读 + 字段展开 |
next | 算接下来 N 次执行时间 |
build | 从人话生成 cron 表达式 |
schtasks | 生成 Windows schtasks /Create 命令 |
lint | 定时坑位体检 |
fields | 字段取值范围速查 |
核心能力(全部实测通过)
1. parse:人话描述 + 字段展开
python scripts/schedule_runner.py parse "*/15 * * * *"
python scripts/schedule_runner.py parse "0 2 * * 1-5"实测 description 逐条(不是把 */15 原样吐回,而是说人话):
| 表达式 | description |
|---|---|
*/15 * * * * | 每 15 分钟 |
0 2 * * 1-5 | 2 时 0 分,周一至周五 |
30 9 * * MON | 9 时 30 分,周一 |
0 */6 * * * | 每 6 小时的第 0 分 |
0 0 * * 0,6 | 0 时 0 分,周六、周日 |
15 3 1 1 * | 3 时 15 分,1 月,1 日 |
字段展开给出 counts(如 minute: 4, hour: 24),便于核对。
2. 别名展开与 OR 语义告警
python scripts/schedule_runner.py parse "@daily"
python scripts/schedule_runner.py parse "0 0 1 * 1"@daily 展开为 0 0 * * *,并附 "note": "别名 @daily 已展开为 0 0 * * *"。
0 0 1 * 1(日+周同时限定)会挂上告警,这是 cron 最反直觉的地方:
{ "description": "0 时 0 分,1 日,周一(日与周同时限定 → 按 cron 规则取「或」,任一满足即执行)",
"warn_or_semantics": "日 与 周 同时被限定:Vixie cron 取「或」(任一匹配即执行),不是「且」。想要「且」得把条件塞进脚本里自己判断" }多数人以为这是「每月 1 号且是周一」,实际是「每月 1 号 或 每个周一」——一周触发 5 次而不是 1 次。
3. next:穷举接下来的执行时间
python scripts/schedule_runner.py next "*/15 * * * *" --from "2026-09-23 10:00" --count 5
next = ['2026-09-23 10:15', '2026-09-23 10:30', '2026-09-23 10:45', '2026-09-23 11:00', '2026-09-23 11:15']
gap_note = 间隔均匀跨周末跳过(工作日 2:00,从周五 2026-09-25 起算,直接跳到下周一 09-28):
2026-09-28 02:00 / 2026-09-29 02:00 / 2026-09-30 02:00 / 2026-10-01 02:00 / 2026-10-02 02:00闰年陷阱(0 0 29 2 *,从 2026 年起算):1500 天窗口内只找到 1 次
{ "next": ["2028-02-29 00:00"], "exhausted": true,
"warn": "1500 天内没凑够 3 次(只找到 1 次),表达式可能永不触发" }不编造:凑不够就 exhausted: true + 如实说明,不给一堆假日期。
4. 非法表达式的错误必须能指导修正
| 输入 | 报错 |
|---|---|
60 * * * * | minute 的取值 60 越界(合法范围 0-59) |
* * * * | 只有 4 段:标准 cron 是 5 段(分 时 日 月 周),少了一段 |
0 0 ? * * | 出现 '?':这是 Quartz/cron-utils 的扩展语法,标准 cron 不认 |
0 0 1 1 0 0 | 收到 6 段…首段若是秒,请去掉(秒级调度用 schtasks /SC MINUTE 更合适) |
0 0 5-1 * * | day-of-month 的区间非法:'5-1'(起点大于终点;跨周/跨月请写成两段,如 22-23,0-6) |
@reboot | 不支持的别名(列出支持的那几个;@reboot 由各实现自定,本工具不认) |
5. build:从人话生成表达式
python scripts/schedule_runner.py build --daily --at 02:30
python scripts/schedule_runner.py build --weekly --weekday MON,WED,FRI --at 09:00| 参数 | 结果 |
|---|---|
--every 15m | */15 * * * * | 每 15 分钟 |
--daily --at 02:30 | 30 2 * * * | 2 时 30 分 |
--weekly --weekday MON,WED,FRI --at 09:00 | 0 9 * * 1,3,5 | 9 时 0 分,周一、周三、周五 |
--monthly --day 1 --at 00:05 | 5 0 1 * * | 0 时 5 分,1 日 |
--hourly --minute 7 | 7 * * * * |
边界也给了可执行的替代方案:
--every 90m -> 90 分钟无法用单条 cron 表达成等距(小时字段的步长只能整除 24)。可选:1h(60 分钟)或 2h(120 分钟),或拆成两条表达式由脚本内判断
--at 25:00 -> --at 时间非法:'25:00'(需 HH:MM,时 0-23 分 0-59)
无任何参数 -> 请指定一种调度:--every 或 --daily/--weekly/--monthly/--hourly6. schtasks:生成 Windows 计划任务命令
python scripts/schedule_runner.py schtasks "30 2 * * *" --name NightBackup --cmd "python D:/bichike/backup.py" --user SYSTEM
schtasks /Create /TN "NightBackup" /TR "python D:/bichike/backup.py" /SC DAILY /ST 02:30 /RU SYSTEM /F/TN 与 /TR 的值一律加引号——不加引号时带空格或反斜杠的命令会自毁。
搬不过去的条件会挂在 unsupported_conditions 里,不会被静默吞掉:
{ "unsupported_conditions": [
"月份限定:schtasks 无「几月」条件,需在脚本里判断",
"该 cron 形态(多分钟/多小时组合)schtasks 单条任务表达不了,建议改用每分钟触发 + 脚本内过滤" ],
"warn": "有条件无法映射到 schtasks,已如实列出——别以为这条命令等价于原 cron" }caveats 里同时说明:schtasks 错过的时间窗默认不补跑、起算点由 /ST 决定、秒级/复杂组合表达不了。
7. lint:定时坑位体检
python scripts/schedule_runner.py lint "0 0 1 * 1"
[ warn ] 「日」与「周」同时被限定 —— Vixie cron 取【或】不是【且】,极易写出「每月 1 号且必…
[ info ] 0 点 0 分是全天最拥挤的时刻:备份/报表都挤在这时候
[ info ] 本工具按本地朴素时间计算,不做夏令时换算;若机器时区有夏令时,02:00-03:00 的调度每年会被…另外两类实测结论:*/7 * * * * 报「分字段步长 */7 不能整除 60,每轮最后一个间隔会变短」;0 0 30 2 * 报「2 月没有 30 日——这条只在闰年触发(29)或永不触发(30/31)」。非法表达式直接 worst = danger。
8. fields:速查表
format = 分 时 日 月 周(5 段,空格分隔)
or_trap = 「日」和「周」同时被限定时取【或】——要【且】请写进脚本工作流建议
- 用户给表达式时:先
parse,把description与warn_or_semantics一起讲——尤其0 0 1 * 1这种,用户八成以为自己写的是「且」。 - 用户给人话时:先
build,再拿生成的表达式parse回来复核一遍,两次描述一致再交付。 - 落 Windows 计划任务前:必须看
unsupported_conditions。非空的就不能说「等价迁移完成」,要说明哪些条件搬不过去、建议怎么在脚本里补。 - 交付时要说清楚:
next若exhausted: true,明确告知「表达式可能永不触发」,而不是列出假日期;- 涉及夏令时地区时,提醒本工具按本地朴素时间计算;
- schtasks 的
/ST是起算点,不是与 cron 等价的语义。
自检清单
- [ ]
parse的description是否与用户原意一致(不含*/n这类原样符号)? - [ ] 日+周双限定时,是否已把 OR 语义讲给用户?
- [ ]
next若exhausted: true,是否如实说明而非给假日期? - [ ]
schtasks的unsupported_conditions为空吗?非空是否已告知用户? - [ ] 跨周末/闰年这类边界,是否用
next验证过而不是凭感觉?
定时执行 · 律令科技(深圳)有限公司 (@lexord-technology) · Proprietary · © 2026
许可与版权
本 Skill 采用 BUSL-1.1 许可(源码可见,可自由使用)。
版权所有 © 2026 律令科技(深圳)有限公司(@lexord-technology)。
允许个人及企业内部免费使用、复制、修改,包括内部生产环境。未经书面许可,不得将本 Skill 或其修改版作为商业服务对外销售、转售或提供托管服务。各版本发布之日起 4 年后自动转为 Apache License 2.0。详见随包 LICENSE.md。
输出规范
- 交付形态:执行结果 + 变更清单,说清动了什么、没动什么。
- 必含字段:执行前状态 / 执行动作 / 执行后状态 / 失败项与原因 / 回滚方式。
- 留痕:产生副作用的执行必须写留痕文件(manifest / log),可回溯。
- 自检:失败项未列原因,或无可回滚路径,视为未完成。
版本:v0.1.5 · 出品:【律令】
反例对照(避开这些写法)
| ❌ 反例 | ✅ 正例 | 判据 |
|---|---|---|
| 高危动作直接执行 | 先 dry-run 预览,人工确认后再落盘 | 这一步做错了能不能一键撤回 |
| 失败只说「失败了」 | 失败项 + 失败原因 + 已回滚到什么状态 | 用户能不能据此判断要不要重试 |
| 重复执行已做过的动作 | 先查留痕文件,已完成的跳过(幂等) | 重跑一次会不会产生重复副作用 |
| 执行完不说改了什么 | 给出变更清单:动了哪些、没动哪些 | 用户能否核对结果 |
<!– WB-SELFCHECK v1 –>
交付前自检(必跑)
本包自带可执行自检脚本。在交付 / 打包 / 发布之前,必须运行并通过:
python scripts/selfcheck.py退出码语义(与本节末尾「退出码(脚本契约)」一致):
| 码 | 含义 | 你要做的事 |
|---|---|---|
| 0 | 全部通过 | 可以交付 |
| 2 | 用法错误 | 检查运行路径,用包根目录下 scripts/selfcheck.py |
| 3 | 门禁未通过 | 按 FAIL 项逐条修好再交付,不要带病交付 |
| 4 | 环境问题 | 检查 Python 版本(需 3.8+)与入口脚本是否可运行 |
| 8 | 部分通过 | 无 FAIL,但有 WARN;建议先修警告项再交付 |
自检覆盖:SKILL.md 与 frontmatter(name·description)/ 合规声明(frontmatter license 或 ATTRIBUTION.md,二者其一即可——第三方转化包常以后者记录归属)/ 必备章节 / 打包卫生(禁止 .pyc·__pycache__·.bak·.zip)/ 脚本可编译 / 入口脚本 --help 可运行。<!– /WB-SELFCHECK –>
退出码(脚本契约)
| 码 | 含义 | 你要对用户说的话 |
|---|---|---|
| 0 | 成功 | 直接给结果,不解释过程 |
| 2 | 输入错误(缺参数 / 格式不对 / 文件不存在) | 「你给的 <X> 不对,需要 <Y>」—— 说明正确格式,不要猜默认值硬跑 |
| 3 | 鉴权/授权失败(密钥缺失、无权限) | 「需要你先提供 <凭据>」—— 说明去哪里拿,不要跳过鉴权 |
| 4 | 服务/环境失败(网络不可用、依赖缺失) | 「这一步依赖 <X> 不可用」—— 给出替代路径或降级方案 |
| 8 | 部分成功(有成功项也有失败项) | 「N 项成功、M 项失败」—— 逐条列出失败项与原因,不要只报总数 |
脚本退出非 0 时:不要静默重试。先把该码对应的话告诉用户,再决定是补齐输入重试、还是换路径。
状态与断点
- 多阶段流程在执行目录写
outputs/.state.json,记录「当前阶段 + 已完成产物路径 + 时间」。 - 每个阶段结束后写一次;中途中断后重启,先读该文件,从断点阶段继续,不从头重跑。
- 状态文件只记阶段与产物路径,不记对话内容、不记敏感数据。
- 发现状态文件与实际情况不符(产物已不存在)时,以实际产物为准并重置状态。