Cron表达式转systemd定时器工具
免费工具,将cron表达式(分 时 日 月 星期)转换为systemd定时器的OnCalendar=语法。同时对日期与星期同时限定时的OR语义差异进行提示,适用于将cron任务迁移到Docker/Kubernetes环境。
cron字段与systemd组成部分对照表
cron表达式的5个字段与systemd的OnCalendar=语法对应关系如下。
| 位置 | cron字段 | systemd对应部分 |
|---|---|---|
| 1 | 分钟 | 时间部分的分钟(HH:MM:SS中的MM) |
| 2 | 小时 | 时间部分的小时(HH:MM:SS中的HH) |
| 3 | 日(日期) | 日期部分的日(年-月-日中的日) |
| 4 | 月 | 日期部分的月(年-月-日中的月) |
| 5 | 星期 | 星期前缀(例如Mon、Mon..Fri) |
由于cron没有秒字段,systemd的秒部分始终为"00"。当日期和月份均不受限(*)时,systemd的年-月-日部分可以完全省略。
cron星期编号与systemd星期缩写对照表
cron用0〜7的数字表示星期,而systemd使用英文星期缩写。
| cron星期编号 | systemd星期缩写 |
|---|---|
| 0 (7) | Sun |
| 1 | Mon |
| 2 | Tue |
| 3 | Wed |
| 4 | Thu |
| 5 | Fri |
| 6 | Sat |
常见转换示例
| cron表达式 | OnCalendar= | 含义 |
|---|---|---|
| * * * * * | OnCalendar=*-*-* *:*:00 | 每分钟执行一次(相当于cron的"* * * * *")。 |
| */15 * * * * | OnCalendar=*:00/15:00 | 每15分钟执行一次。 |
| 0 9 * * 1-5 | OnCalendar=Mon..Fri 09:00:00 | 工作日(周一至周五)上午9点执行。 |
| 0 0 1 * * | OnCalendar=*-*-01 00:00:00 | 每月1日0点执行。 |
| 0 0 1 1 * | OnCalendar=*-01-01 00:00:00 | 每年1月1日0点执行。 |
| 0 0 1 * 1 | OnCalendar=Mon *-*-01 00:00:00 | 同时指定日期(1日)与星期(周一)的示例。在cron中这是OR条件(满足其一即可执行),但在systemd中会变为AND条件(必须同时满足才执行),因此转换结果的执行频率会低于原cron表达式。 |
同时限定日期与星期(均不为"*")的cron表达式,无法通过systemd的OnCalendar语法准确转换,因为cron在此情形下是OR语义,而systemd始终是AND语义。建议将此类情况拆分为两个独立的systemd定时器。
使用提示
- 如果将日期与星期都设为非"*",cron的OR条件无法用systemd的AND条件准确表达。请查看转换结果中的警告,必要时拆分为两个定时器。
- 一些最小化的容器基础镜像(例如基于Alpine的Docker镜像)根本不包含cron守护进程,此时systemd定时器是迁移计划任务的实用替代方案。
- 可以使用"systemd-analyze calendar"命令验证生成的OnCalendar行,该命令还会显示接下来的计划执行时间。
- 与单行crontab不同,systemd定时器由两个文件组成:.timer单元(计划部分)和.service单元(实际执行的任务)。
- 对于不同时组合日期与星期的简单计划(每小时、每天、每周等),本转换结果始终是精确的。
常见问题
闲话 ― 从cron到systemd定时器
systemd大约于2010年前后作为管理Linux启动流程的初始化系统出现,此后成为大多数发行版的标准配置。其中的定时器功能与cron类似,提供周期性执行能力,但增加了cron从未拥有的功能:依赖关系解析、通过journalctl集中管理执行日志,以及可配置的失败重试行为。
与此同时,Docker和Kubernetes等容器环境中,为了保持镜像体积小巧,越来越多的基础镜像根本不包含cron守护进程。当需要在此类环境中运行周期性任务时,现实的选择要么依赖Kubernetes CronJob等编排层面的机制,要么在主机本身运行systemd的情况下交给systemd定时器处理。
OnCalendar=语法比cron的5个字段表达能力更强,支持指定年份精度和秒级精度,但正因如此,一些cron表达式(同时限定日期与星期的OR条件)在简单转换下会改变含义。本工具明确地提示这一警告,正是为了让迁移过程不至于陷入这个容易被忽略的陷阱。