Jenkins 定时触发(cron)使用说明
1) 基本格式(Jenkins 特有)
Jenkins 使用类 cron 的 5 字段格式(与 Linux crontab 类似,但仅 5 字段):
MIN HOUR DOM MONTH DOW
字段含义:
- MIN:分钟(0–59)
- HOUR:小时(0–23)
- DOM:日(1–31)
- MONTH:月(1–12 或英文缩写)
- DOW:星期(0–7,0 和 7 都表示星期日)
注意:Jenkins 的调度是“cron-like”,有少量差异(见下文)。
2) Jenkins 专属/扩展语法
-
H(Hash):Jenkins 的关键扩展。表示“哈希后的固定分布值”——根据 Job 名称(或 job path)计算一个固定分钟或小时值,用于把大量任务的触发时间散列开,避免同时打到控制器。例:H 23 * * *不代表“随机每次不定”,而是“根据 Job 固定算出一个分钟(例如 32)”,每天在 23:32 执行。 -
H(n-m):在区间内取哈希后的一个值,表示“在 n 到 m 之间的某一分钟/小时”。例如H(10-20) 23 * * *表示在 23:10–23:20 之间的某一分钟(固定选值,基于 job 名称)。 -
H/step和H与/组合:可用于分散周期,例如H/15 * * * *(每 15 分钟,但偏移由哈希决定以分散负载)或H */4 * * *(每 4 小时,但小时使用哈希分布)。官方 Pipeline 示例也展示了类似用法。 -
其他标准 cron 特性:数字、逗号分隔(列表)、连字符(范围)、斜线(步长,如
*/5)等均可。 -
插件扩展:若需要更高级功能(比如显式时区、多行时区、或“每月最后一天”等复杂规则),可以使用像 Extended Timer Trigger 这样的插件来扩展语法与时区支持。
3) 常见表达式 & 含义(实战模板)
下面把常见业务场景列出来,你可以直接复制到 Jenkins 的「构建触发器 → 定期构建」或 Pipeline 的 cron(...) 中:
-
每天 23:00(整点)
0 23 * * *固定在 23:00 执行(推荐用该写法想要整点触发时)。
-
每天 23 点,但不同 Job 分散分钟(避免整点拥堵)
H 23 * * *每个 Job 会被分配到 23:00–23:59 的某一分钟(固定,对这个 job 不变)。
-
每天 23:10–23:20 之间的某一分钟(分散在窗口内)
H(10-20) 23 * * *适合把一类任务集中到某个小时但再均摊到窗口内。
-
每隔 15 分钟执行一次
*/15 * * * *或(使用 H 分散):
H/15 * * * *注意:大量使用
*/n可能造成多个任务同一时刻触发,建议用H/做分散。([CloudBees][6]) -
工作日(周一到周五)每 4 小时分散执行
H */4 * * 1-5Pipeline 的官方示例就有类似写法。
-
每周一 23:00
0 23 * * 1 -
每月第一天凌晨 2 点
0 2 1 * * -
每分钟(测试用,勿在生产大量任务使用)
* * * * *
4) Pipeline(Jenkinsfile)中如何写
- 在 Declarative Pipeline 中:
pipeline {agent anytriggers {cron('H 23 * * *')}stages { ... }
}
- 在 Scripted Pipeline 或单独触发项也可用
triggers { cron('...') }或properties([pipelineTriggers([cron('...')])])。官方文档有示例。
5) 常见问题与坑
-
为什么
H 23 * * *出现在 23:32?
因为H根据 job 名称哈希后会选择一个固定分钟(比如 32)。这不是随机每次变化,而是“固定的散列时间”。如果你需要精确整点,用0 23 * * *。 -
日与星期冲突:Jenkins 跟标准 cron 一样,如果同一行同时指定了 DOM(日期)和 DOW(星期),默认是“或”的关系(只要任一满足就触发)。如果你需要更精确控制,拆成多行或在脚本里判断日期。(不同 cron 实现行为略有差异,Jenkins 文档说明以 5 字段为准)。
-
每月最后一天 / L / W 支持有限:标准 cron 某些扩展(如
L,W,#)在 Jenkins 上并不是全部原生支持。若需要“每月最后一天”等复杂逻辑,建议使用插件或写多行表达式 / 在 job 脚本里判断日期。社区也常推荐用 Extended Timer Trigger 插件 来弥补。 -
时区(Timezone)问题:Jenkins 默认以控制器(master)所在系统时区为准。某些插件(Extended Timer Trigger)允许为单个定时规则指定时区。如果你的团队跨区并需要以特定时区触发,考虑使用插件或在脚本里做时区判断。
-
大量相同时间点触发会压垮控制器:尽量避免大量 job 写
0 0 * * *之类的整点触发。推荐用H或分散窗口(如H(0-30) 2 * * *)来缓解并发压力。 -
注释/空行:Jenkins 的“定期构建”文本框中可以写多行,每行一个表达式。以
#开头的行为注释。空行与注释行会被忽略。
6) 进阶技巧
- 统一使用
H策略:所有每天/每小时执行但不要求精确时间的任务,尽量用H或H(n-m),可以显著降低控制器瞬时负载。 - 按业务分批次窗口:例如把“数据同步”类任务都安排在 01:00–02:00 的不同分钟(
H(0-59) 1 * * *),把“报表类”放在 02:00–03:00。 - 结合并发限制:如果 Job 会占用大量资源,配合
throttle-concurrents插件或节点标签限制并发执行数量。 - 用环境判断替代复杂 cron:某些“每月最后一天”可以用每日触发 + 脚本内
if is_last_day_of_month()判断来代替复杂 cron 写法(更可靠,易维护)。 - 日志/构建参数对照:当使用
H后若想知道具体触发分钟,查看 Job 的最近一次构建时间或在 Job 配置的帮助里查看 Jenkins 为该 job 计算出的值(UI 有时能显示)。
7) 典型场景速查表(可直接复制)
| 场景 | 表达式 | 说明 |
|---|---|---|
| 每天 23:00 | 0 23 * * * | 精确整点 |
| 每天 23 点分散(避免整点) | H 23 * * * | Jenkins 根据 job 固定分配一个分钟 |
| 每天 23:10–23:20 窗口内分散 | H(10-20) 23 * * * | 在窗口内分摊 |
| 每 15 分钟 | */15 * * * * | 精确每 15 分钟 |
| 每 15 分钟(分散) | H/15 * * * * | 使用哈希做偏移,分散触发 |
| 每周一 23:00 | 0 23 * * 1 | 周一整点 |
| 工作日每 4 小时分散 | H */4 * * 1-5 | pipeline 示例常见写法。 |
8) 简短故障排查流程
- 任务在意料之外的分钟触发:确认是否用了
H或H(n-m);若要固定时间改为具体数字。 - 某月没有触发(比如 31 日):检查你是否写了
31,某些月份没有 31,会导致无触发;考虑写多行或脚本判断最后一天。 - 时区不对:检查 Jenkins 控制器系统时区,若需单规则时区,考虑 Extended Timer Trigger 插件。
9) 实际 Jenkinsfile 示例
把下面拷到 Jenkinsfile 可直接验证(每天 23:00 用 H 散列):
pipeline {agent anytriggers {// 每天 23 点,在 23:00-23:59 的某一分钟运行(由 Jenkins 基于 job 名称决定具体分钟)cron('H 23 * * *')}stages {stage('Build') {steps {echo "Run at ${new Date()}"}}}
}
若要精确 23:00:
triggers { cron('0 23 * * *') }
10) 小结
- Jenkins 使用 5 字段 cron;
H是 Jenkins 的“哈希分散”关键字,用于把触发时间均摊以避免峰值。 - 想要精确时间就写具体数字(
0 23 * * *);想要分散触发就用H或H(...)。 - 复杂需求(最后一天、指定时区)可能需要插件或脚本判断(Extended Timer Trigger 可选)。
