@fureweb/cronly
v1.0.0
Published
Schedule JavaScript scripts for everyday jobs, with cron expressions when you need them.
Maintainers
Readme
Cronly
轻松调度脚本 — 无需 cron 语法。 直接表达你的意思:每天 8 点、工作日 9 点、每 4 小时。 需要时也可以直接使用 cron expression。Cronly 会在底层安全地管理 crontab 条目。
1 分钟上手
# 每天 8:00 运行
cronly add ./daily-report.mjs --daily 08:00
# 相同含义的 cron expression
cronly add ./daily-report.mjs --schedule "0 8 * * *"
# 工作日 9:00 运行
cronly add ./notify.mjs --weekdays --at 09:00
# 相同含义的 cron expression
cronly add ./notify.mjs --schedule "0 9 * * 1-5"
# 每 4 小时运行
cronly add ./sync.mjs --every-hours 4
# 相同含义的 cron expression
cronly add ./sync.mjs --schedule "0 */4 * * *"
# 每周六 0:00 运行
cronly add ./weekly-cleanup.mjs --weekly sat --at 00:00
# 相同含义的 cron expression
cronly add ./weekly-cleanup.mjs --schedule "0 0 * * 6"
# 查看这个工具管理的条目
cronly list适合这些场景:
- 想用
--daily、--weekdays、--every-hours这样直观的标志来调度脚本 - 不想记 cron 语法也能设置常见调度
- 复杂场景下想直接使用 cron expression(
--schedule "0 */6 * * 1-3") - 不想手动编辑其他已有的 crontab 条目
- 想对同一个文件重复执行
add来更新调度
为什么需要?
使用 crontab -e 手动管理会导致以下问题:
- 不小心将同一脚本注册两次
- 难以一眼判断哪个条目对应哪个脚本
- 注册、修改、删除时可能误改其他 cron 条目
- 脚本路径变更时忘记同步 crontab
Cronly 解决了这些问题:
| 手动管理 crontab | Cronly |
|---|---|
| 可能重复注册 | 基于绝对路径自动去重 |
| 可能误编辑其他条目 | 仅修改管理块,完全隔离 |
| 难以识别条目 | 通过元数据注释识别 |
| 变更时需手动同步 | add 以 upsert 方式运行 |
特性
- 零外部 npm 依赖 — 仅使用 Node.js 内置模块
- 无需 DB、服务器或守护进程 — 实际 crontab 是唯一数据源
- 管理条目带有元数据注释,与现有手动条目完全隔离
- 包含空格、单引号和
%的路径会被安全地进行 shell 引用处理 - 支持 cron 别名(
@reboot、@daily、@weekly等) - 基于 ESM(
"type": "module") - Node.js >= 14.8.0
安装
# 从 npm 安装
npm install -g @fureweb/cronly
# 无需安装直接使用
npx @fureweb/cronly
# 本地开发
git clone https://github.com/fureweb-com/cronly.git
cd cronly
npm link全局安装后,运行命令仍然是 cronly。
使用方法
注册脚本
# 每天 2:00 运行
cronly add ./backup.sh --daily 02:00
# 每 10 分钟运行
cronly add ./report.mjs --every-minutes 10
# 周一、三、五 9:00 运行
cronly add ./class.mjs --days mon,wed,fri --at 09:00
# 周末 10:00 运行
cronly add ./weekend-job.mjs --weekends --at 10:00
# 开机时运行一次
cronly add ./startup.sh --reboot
# 显式指定运行时
cronly add ./custom-binary --daily 08:00 --runtime exec对同一文件再次执行 add 时,以更新而非新增方式运行:
# 首次:注册
cronly add ./backup.sh --daily 02:00
# 再次:更改调度(不会重复注册)
cronly add ./backup.sh --daily 03:00简易调度模式
| 标志 | 示例 | cron 转换结果 |
|------|------|--------------|
| --daily HH:MM | --daily 08:00 | 0 8 * * * |
| --every-hours N | --every-hours 4 | 0 */4 * * * |
| --every-minutes N | --every-minutes 10 | */10 * * * * |
| --weekly 星期 --at HH:MM | --weekly mon --at 10:00 | 0 10 * * 1 |
| --days 星期,... --at HH:MM | --days mon,wed,fri --at 09:00 | 0 9 * * 1,3,5 |
| --weekdays --at HH:MM | --weekdays --at 08:30 | 30 8 * * 1-5 |
| --weekends --at HH:MM | --weekends --at 10:00 | 0 10 * * 0,6 |
| --reboot | --reboot | @reboot |
星期标记:sun、mon、tue、wed、thu、fri、sat(不区分大小写)
Cron expression 直接输入(高级)
以上模式无法覆盖的场景,可以用 --schedule 直接指定:
# 周一至周三每 6 小时
cronly add ./report.mjs --schedule "0 */6 * * 1-3"
# 每月 15 日 9:00
cronly add ./monthly.mjs --schedule "0 9 15 * *"查看列表
cronly list输出示例:
a1b2c3d4 0 2 * * * /home/user/backup.sh (sh)
e5f6a7b8 */10 * * * * /home/user/report.mjs (node)删除
# 按文件路径删除
cronly remove ./backup.sh
# 按 id 删除
cronly remove --id a1b2c3d4原始输出
cronly print输出管理中条目的实际 crontab 块。
环境检查
cronly doctor检查 Node.js 版本、crontab 命令是否存在,以及 crontab 是否可读。
防重复注册机制
- 将脚本文件规范化为绝对路径(
path.resolve) - 使用绝对路径的 SHA-256 哈希前8个字符作为去重 id
add时如果已存在相同 id 的块,则替换(upsert)- 否则追加新块
crontab 内部格式
# 现有手动条目(不做修改)
0 * * * * /usr/bin/some-other-job
# [cronly:begin] id=a1b2c3d4 path=/home/user/backup.sh runtime=sh
0 2 * * * '/bin/sh' '/home/user/backup.sh'
# [cronly:end] id=a1b2c3d4使用 # [cronly:begin] / # [cronly:end] 块包裹,与其他手动条目完全隔离。
测试
npm test项目结构
├── bin/cronly.mjs # CLI 入口
├── lib/
│ ├── cli.mjs # argv 解析、帮助文本
│ ├── commands.mjs # add/list/remove/print/doctor 实现
│ ├── crontab.mjs # crontab 读写(child_process)
│ └── entry.mjs # 条目构建/解析/去重
├── test/
│ ├── test.mjs # 单元测试
│ └── integration.mjs # 集成测试(实际 crontab)
├── package.json
└── LICENSE未来扩展方向
- dry-run 模式:使用
--dry-run标志预览更改而不修改 crontab - 导入/导出:以 JSON 备份/恢复管理条目
- 日志路径自动设置:自动追加
>> /path/to/log 2>&1选项 - 环境变量注入:设置 cron 执行时的 PATH 等环境变量
- MAILTO 设置:每个条目的错误通知邮件设置
- 分组/标签:按组批量管理条目
- cron 表达式验证:预先验证 schedule 值的有效性
- overlap 防止:基于 flock 的并发执行防护
限制
- 仅支持用户 crontab(
crontab -l/crontab -) - 不支持 systemd timer 和
/etc/cron.d - 不支持分布式环境(仅限单机)
- 不包含 overlap execution 防止
- 不支持包含换行或 carriage return 字符的路径
许可证
MIT
