Cron 表达式详解:完整语法指南
· 12 分钟阅读
📑 目录
Cron 是类 Unix 操作系统中基于时间的任务调度器。如果你需要在午夜运行脚本、每周日备份数据库、每小时清理临时文件,或在每月第一天发送报告,cron 就是你的工具。但它的表达式语法——那些像 0 */6 * * 1-5 这样的神秘字符串——一开始可能会让人望而生畏。
本指南将完全揭开 cron 表达式的神秘面纱。你将学习每个字段、每个特殊字符,看到数十个真实世界的模式,并理解那些连经验丰富的开发者都会遇到的时区陷阱。无论你是在调度备份、运行维护脚本还是自动化报告,掌握 cron 语法对任何开发者或系统管理员来说都是必不可少的。
Cron 表达式的结构
标准的 cron 表达式有五个用空格分隔的字段。每个字段代表一个时间单位,它们共同定义了任务应该何时运行。
┌───────────── 分钟 (0-59)
│ ┌─────────── 小时 (0-23)
│ │ ┌───────── 日期 (1-31)
│ │ │ ┌─────── 月份 (1-12)
│ │ │ │ ┌───── 星期 (0-6, 0=周日)
│ │ │ │ │
* * * * * 要执行的命令
每个字段可以包含数字、范围、列表、步进值或通配符。cron 的美妙之处在于这些简单的构建块组合起来可以创建极其灵活的调度模式。
一些 cron 实现支持第六个字段表示秒,第七个字段表示年份,但标准的五字段格式是通用支持的,也是你在大多数类 Unix 系统(包括 Linux、macOS 和 BSD 变体)中会遇到的。
五个字段详解
理解每个字段的范围和行为对于编写正确的 cron 表达式至关重要。让我们系统地检查每一个。
| 字段 | 范围 | 特殊字符 | 示例 |
|---|---|---|---|
| 分钟 | 0-59 | * , - / | */15 (每15分钟) |
| 小时 | 0-23 | * , - / | 9-17 (上午9点到下午5点) |
| 日期 | 1-31 | * , - / L W | 1,15 (1号和15号) |
| 月份 | 1-12 或 JAN-DEC | * , - / | 1-6 (1月到6月) |
| 星期 | 0-6 或 SUN-SAT | * , - / L # | 1-5 (周一到周五) |
分钟字段 (0-59)
分钟字段控制任务在小时的哪一分钟运行。值 0 表示整点,30 表示半点,59 是小时的最后一分钟。
常见模式包括 */5 表示每5分钟,0,30 表示每小时两次,或 15 表示每小时的15分。
小时字段 (0-23)
小时使用24小时制,其中 0 是午夜,12 是正午,23 是晚上11点。这是习惯于12小时 AM/PM 表示法的开发者最常见的困惑来源之一。
工作时间通常表示为 9-17(上午9点到下午5点),而夜间维护可能使用 0-6(午夜到早上6点)。
日期字段 (1-31)
此字段指定在月份的哪一天运行。有效值是 1 到 31,尽管并非所有月份都有31天。Cron 会优雅地处理这个问题——如果你在2月指定31号,该任务在那个月就不会运行。
特殊字符 L 表示"月份的最后一天",会自动调整月份长度和闰年。
月份字段 (1-12)
月份可以用数字指定(1 表示1月到 12 表示12月)或使用三字母缩写(JAN、FEB、MAR 等)。在大多数实现中,缩写不区分大小写。
季度计划通常使用 1,4,7,10(1月、4月、7月、10月)或 3,6,9,12 表示财政季度末等模式。
星期字段 (0-6)
星期范围从 0(周日)到 6(周六)。一些系统也接受 7 作为周日以方便使用。也支持三字母缩写(SUN、MON、TUE 等)。
最常见的模式是 1-5 表示工作日(周一到周五),而 0,6 或 6,0 表示周末。
专业提示:当日期和星期都被指定(不是通配符)时,任务在任一条件满足时运行(OR 逻辑),而不是两者都满足。这让许多开发者措手不及。例如,0 0 13 * 5 在每月13号和每个周五运行,而不仅仅是13号星期五。
特殊字符说明
特殊字符赋予 cron 表达式强大的功能和灵活性。每个字符在定义调度模式时都有特定的用途。
星号 (*) - 通配符
星号表示该字段的"每个可能的值"。它是最常用的特殊字符,几乎出现在每个 cron 表达式中。
* * * * *— 每天的每一分钟运行0 * * * *— 每小时的整点运行0 0 * * *— 每天午夜运行
逗号 (,) - 列表分隔符
逗号让你指定多个离散值。当你需要特定的、非连续的时间时,这非常完美。
0 9,12,15,18 * * *— 在上午9点、正午、下午3点和下午6点运行0 0 1,15 * *— 在每月1号和15号的午夜运行0 0 * * 1,3,5— 在周一、周三和周五的午夜运行
连字符 (-) - 范围操作符
连字符定义包含范围,使指定连续时段变得容易。
0 9-17 * * *— 从上午9点到下午5点每小时运行0 0 * * 1-5— 周一到周五的午夜运行0 0 1-7 1 *— 1月的第一周每天运行
斜杠 (/) - 步进值
斜杠指定步进间隔,允许你在范围内以固定间隔运行任务。语法是 起始/步进 或 */步进 表示整个范围。
*/15 * * * *— 每15分钟 (0, 15, 30, 45)0 */2 * * *— 每2小时 (0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22)0 0 */3 * *— 每3天 (1号、4号、7号、10号等)0 9-17/2 * * *— 上午9点到下午5点之间每2小时 (9, 11, 13, 15, 17)
快速提示:*/15 不是指"从现在开始每15分钟"——它是指每小时的0、15、30和45分。如果你在10:07添加一个 cron 任务,*/15 模式将首先在10:15运行,而不是10:22。
L - 最后一天
L 字符表示"最后",用于日期和星期字段。它对于需要考虑不同月份长度的月末处理特别有用。
0 0 L * *— 在每月最后一天的午夜运行0 0 * * L— 在一周最后一天(周六)的午夜运行0 0 * * 5L— 在每月最后一个周五运行
W - 最近的工作日
W 字符查找给定日期最近的工作日。如果指定的日期落在周末,任务将在最近的工作日运行。
0 0 15W * *— 在最接近15号的工作日运行0 0 1W * *— 在月份的第一个工作日运行0 0 LW * *— 在月份的最后一个工作日运行
井号 (#) - 第N个星期几
井号字符指定月份内星期几的第N次出现。语法是 星期#次数。
0 0 * * 1#1— 每月第一个周一0 0 * * 5#2— 每月第二个周五0 0 * * 3#4— 每月第四个周三
请注意,L、W 和 # 并非所有 cron 实现都支持。它们在现代版本如 Vixie cron 和大多数基于云的调度器中可用,但在较旧的 Unix 系统中可能不起作用。
常见 Cron 模式
让我们看看你会经常使用的真实世界调度模式。这些示例涵盖了最常见的自动化场景。
每分钟、每小时和每天
* * * * *— 每分钟(谨慎使用,可能造成负载问题)0 * * * *— 每小时的0分0 0 * * *— 每天午夜0 12 * * *— 每天正午
每天多次
0 0,12 * * *— 每天两次,在午夜和正午0 */6 * * *— 每6小时 (0:00, 6:00, 12:00, 18:00)0 8,12,16,20 * * *— 每天四次在特定小时*/30 * * * *— 每30分钟
每周计划
0 0 * * 0— 每周日午夜0 0 * * 1-5— 工作日午夜0 9 * * 1— 每周一上午9点0 0 * * 6,0— 周末午夜
每月计划
0 0 1 * *— 每月第一天午夜0 0 L * *— 每月最后一天午夜0 0 1,15 * *— 每月1号和15号0 0 1 */3 *— 每季度第一天(1月、4月、7月、10月)
工作时间和维护窗口
0 9-17 * * 1-5— 工作时间每小时(上午9点-下午5点,周一至周五)*/15 9-17 * * 1-5— 工作时间每15分钟0 2 * * *— 每天凌晨2点(常见维护窗口)0 3 * * 0— 每周日凌晨3点(每周维护)
| 使用场景 | Cron 表达式 | 描述 |
|---|---|---|
| 数据库备份 | 0 2 * * * |
每天凌晨2点 |
| 日志轮转 | 0 0 * * 0 |
每周日午夜 |
| 清理缓存 |