终极定时任务:Cron表达式大全与深度解析 (2025更新版)

一、引言:为什么你需要这份大全?

在软件开发与系统运维中,定时任务是自动化不可或缺的一环。无论是每天凌晨备份数据库、每小时清理缓存、还是每5分钟检查服务状态,都需要一个可靠的任务调度机制。而cron表达式,正是定义这种时间计划的标准语言

然而,cron表达式看似简单(* * * * *),其语法细节和特殊字符却常常让人困惑:

  • ? 和 * 在日期和星期字段有什么区别?

  • 如何实现“每月最后一个周五”?

  • Spring和Linux Crontab的表达式为何不完全兼容?

  • LW# 这些符号怎么用?

本文旨在提供一份最全面、最清晰、最实用的cron表达式参考大全,涵盖基础语法、海量示例、特殊用法、不同系统差异以及避坑指南,助你彻底掌握定时任务调度!


二、Cron表达式核心语法 (7字段标准)

一个完整的cron表达式通常由 7个时间字段组成(部分系统如Linux Crontab是5或6位,稍后解释),字段间用空格分隔。每个字段代表不同的时间单位。

字段顺序字段含义允许值范围允许的特殊字符必填
1秒(Seconds)0-59, - * /
2分(Minutes)0-59, - * /
3时(Hours)0-23, - * /
4日(Day of month)1-31, - * / ? L W
5月(Month)1-12 或 JAN-DEC, - * /
6星期(Day of week)0-7 (0和7都代表周日) 或 SUN-SAT, - * / ? L #
7年(Year - 可选)1970-2099 或 *, - * /

📌 重要说明

  1. 字段顺序: 必须严格按照 秒 分 时 日 月 星期 [年] 的顺序。

  2. 星期表示:

    • 0 或 7 = 星期日 (Sunday)

    • 1 = 星期一 (Monday)

    • ...

    • 6 = 星期六 (Saturday)

    • 英文缩写 (SUNMONTUEWEDTHUFRISAT) 通常也支持(取决于具体实现)。

  3. 年字段 (第7位):

    • 在标准的 Unix/Linux Crontab 中通常没有年字段(只有5位:分 时 日 月 星期)。

    • 在 Java生态(如Spring @Scheduled, Quartz)以及一些现代调度系统中通常支持年字段(7位)

    • 如果省略年字段(6位表达式),表示每年都执行。

  4. 日期(Day of month) 和 星期(Day of week) 字段的互斥性:

    • 这两个字段在逻辑上存在一定冲突(一个指定月份中的哪一天,一个指定星期几)。

    • 为了避免歧义,其中一个字段通常必须被设置为 ?(不指定),而另一个字段设置具体值。不能两个字段同时设置具体值(* 除外,它表示“每”)。

    • ? 仅在  和 星期 字段有效。


三、特殊字符详解:解锁高级用法

字符名称作用可用字段示例说明
*星号 (Any)所有值 / 每一所有字段* 在分钟字段 = 每分钟
?问号 (Blank)不指定值。仅在  和 星期 字段使用,解决它们之间的互斥问题。一个设置具体值,另一个就用?日、星期0 0 12 ? * MON = 每周一中午12点
-连字符 (Range)范围所有字段10-15 在分钟字段 = 第10,11,12,13,14,15分钟
,逗号 (And)多个值所有字段MON,WED,FRI 在星期字段 = 周一、三、五
/斜杠 (Step)间隔频率A/B 表示从A开始,每隔B执行一次。所有字段0/15 在秒字段 = 第0,15,30,45秒
*/5 * * * * ? = 每5秒
LLast最后。不同字段含义不同:
字段:L = 当月最后一天
星期字段:L = 周六 (7SAT)
组合L-3 = 倒数第几天
日、星期0 0 L * ? = 每月最后一天午夜
0 0 ? * 6L = 每月最后一个周五 (6=周五, L=最后)
WWeekday最近工作日 (Nearest Weekday)。指定日期,如果该日期是周末,则调整到最近的工作日(周一-周五)。只能用于日字段。通常与具体日期组合使用。 (主要)15W 在日字段:
- 如果15号是工作日 -> 15号
- 如果15号是周六 -> 14号(周五)
- 如果15号是周日 -> 16号(周一)
LW = 本月最后一个工作日
#Number Sign第N个星期XX#N 表示每月的第N个星期X。
X=星期几(1-7 or SUN-SAT), N=第几个(1-5)
星期0 0 ? * 6#3 = 每月第3个星期五中午12点 (6=周五, 3=第三个)
CCalendar日历 (Calendar)。在Quartz Scheduler中引入,含义更复杂(如:5C 在日字段 = 日历中5号之后(包含5号)的第一天)。使用较少,且实现可能不一致(Quartz扩展) 日、星期非标准,建议谨慎使用

四、超级实用示例大全 (按执行频率分类)

🕒 1. 每秒 / 每分钟 / 每小时

表达式含义适用系统
* * * * * ? *每秒执行一次Spring, Quartz
*/1 * * * * ? *每秒执行一次 (同上)Spring, Quartz
0 * * * * ? *每分钟的第0秒执行 (每分钟一次)Spring, Quartz
0 */1 * * * ? *每分钟执行一次 (同上)Spring, Quartz
0 0 * * * ? *每小时的0分0秒执行 (每小时一次)Spring, Quartz
0 0 */1 * * ? *每小时执行一次 (同上)Spring, Quartz
0 0 * * * *Linux Crontab 每小时执行 (注意无秒和年)Linux Crontab

📅 2. 每天 (特定时间)

表达式含义适用系统
0 0 0 * * ? *每天凌晨00:00:00执行Spring, Quartz
0 0 3 * * ? *每天凌晨03:00:00执行Spring, Quartz
0 30 12 * * ? *每天中午12:30:00执行Spring, Quartz
0 0 18 * * ? *每天下午18:00:00执行Spring, Quartz
0 15 10 * * ? 20252025年每天上午10:15:00执行Spring, Quartz
0 0 0,12 * * ?每天中午12点和午夜00点各执行一次Spring, Quartz
0 0 9-17 * * ?每天上午9点到下午5点期间,每小时执行一次 (9,10,11,12,13,14,15,16,17)Spring, Quartz
0 0 9,13,17 * * ?每天上午9点、下午1点、下午5点各执行一次Spring, Quartz
0 0 12 * * *Linux Crontab 每天中午12:00执行Linux Crontab

📆 3. 每周 (特定星期几)

表达式含义适用系统
0 0 10 ? * MON *每周一上午10:00执行Spring, Quartz
0 0 12 ? * MON-FRI *每周一至周五中午12:00执行Spring, Quartz
0 0 9 ? * MON,WED,FRI *每周一、三、五上午09:00执行Spring, Quartz
0 0 15 ? * 6 *每周六下午15:00执行 (6=周六)Spring, Quartz
0 0 0 ? * 7 *每周日凌晨00:00执行 (7=周日)Spring, Quartz
0 0 8 * * 1Linux Crontab 每周一上午8:00执行 (1=周一)Linux Crontab

🗓️ 4. 每月 (特定日期)

表达式含义适用系统
0 0 6 1 * ? *每月1号早上06:00执行Spring, Quartz
0 0 20 15 * ? *每月15号晚上20:00执行Spring, Quartz
0 0 12 5,15,25 * ? *每月5号、15号、25号中午12:00执行Spring, Quartz
0 0 9 1-5 * ? *每月1号到5号,每天上午09:00执行Spring, Quartz
0 0 0 L * ? *每月最后一天午夜00:00执行Spring, Quartz
0 0 12 LW * ? *每月最后一个工作日中午12:00执行Spring, Quartz
0 0 9 15W * ? *每月最接近15号的工作日上午09:00执行 (如果15号是周末,调整到临近工作日)Spring, Quartz
0 0 10 * * 1Linux Crontab 每月1号上午10:00执行 (注意星期字段是*,Linux Crontab 中日期和星期都有效时会都触发,通常建议一个用*一个用具体值或?,但Linux Crontab不支持?,所以需小心)Linux Crontab (谨慎)

🎯 5. 每月 (特定星期)

表达式含义适用系统
0 0 10 ? * 6#2 *每月第2个星期五上午10:00执行 (6=周五, #2=第二个)Spring, Quartz
0 0 8 ? * 1#1 *每月第1个星期一上午08:00执行 (1=周一, #1=第一个)Spring, Quartz
0 0 15 ? * 7L *每月最后一个星期六下午15:00执行 (7=周六, L=最后)Spring, Quartz
0 0 9 ? * 3L *每月最后一个星期三上午09:00执行 (3=周三, L=最后)Spring, Quartz

🎄 6. 每年 (特定日期)

表达式含义适用系统
0 0 0 1 1 ? *每年1月1日00:00执行 (元旦)Spring, Quartz
0 0 12 24 12 ? *每年12月24日中午12:00执行 (平安夜)Spring, Quartz
0 0 9 1 6 ? 20252025年6月1日上午09:00执行Spring, Quartz

⏱️ 7. 复杂间隔与组合

表达式含义适用系统
0 0/5 * * * ? *每5分钟执行一次 (在每分钟的0,5,10,15...55秒触发)Spring, Quartz
0 */10 * * * ? *每10分钟执行一次 (同上)Spring, Quartz
0 0 0/4 * * ? *每4小时执行一次 (0:00, 4:00, 8:00, 12:00, 16:00, 20:00)Spring, Quartz
0 0,30 9-17 * * MON-FRI *工作日(周一到周五)上午9点到下午5点期间,每小时0分和30分各执行一次 (如9:00, 9:30, 10:00, 10:30...17:00, 17:30)Spring, Quartz
0 15 10 L-2 * ? *每月倒数第2天上午10:15执行Spring, Quartz
0 0 8 ? * MON#1 *每月第1个星期一上午8:00执行Spring, Quartz
*/15 * * * * *Linux Crontab 每15秒执行一次 (非标准实现,通常cron最小粒度是分钟,需要特殊技巧如多行或sleep)Linux Crontab (非标准)
0,30 * * * * *Linux Crontab 每分钟的0秒和30秒执行 (相当于每30秒一次)Linux Crontab (非标准)
*/15 * * * *Linux Crontab 每15分钟执行一次 (标准分钟级)Linux Crontab

五、不同系统差异与注意事项 (避坑指南)

  1. 字段数量差异:

    • Linux/Unix Crontab (5位): 标准格式为 分 时 日 月 星期 (无)。执行用户的环境变量(如PATH)会影响命令查找,强烈建议脚本中使用绝对路径

    • Linux/Unix Crontab (6位 - 部分系统): 有些实现(如某些cronie版本)支持6位,第一位是 (秒 分 时 日 月 星期),但仍然无年字段非普遍支持,需确认系统版本

    • Spring @Scheduled / Quartz Scheduler (6位或7位): 通常支持6位 (秒 分 时 日 月 星期) 或7位 (秒 分 时 日 月 星期 年)。字段可选。这是Java生态中最常见的格式

  2. 星期表示差异:

    • Linux Crontab: 通常 0 和 7 都代表周日。1=周一 ... 6=周六。

    • Spring/Quartz: 同样遵循 1=周一 ... 7=周日 (0 有时也代表周日,但建议使用7SUN以保证兼容性)。

  3. 特殊字符支持:

    • ? 在Linux Crontab中通常不支持 ? 字符! 这是最大的坑。在Linux Crontab中,如果你想忽略“日”字段而指定“星期”字段,你只能把“日”字段设为*,但这意味着“日”和“星期”字段都会生效(即满足任意一个条件就触发)。要精确指定星期几,通常需要依赖脚本逻辑或在表达式中小心处理(如* * * * 1 表示每月1号每周一都触发)。Spring/Quartz 支持 ? 解决此问题。

    • LW# 这些通常不是标准POSIX cron的功能。它们主要存在于Quartz Scheduler及其衍生实现(如Spring Task)中。标准的Linux crontab (vixie-croncronie不支持 LW#

  4. 环境变量:

    • Linux Crontab: Cron任务运行的环境不同于用户登录shell的环境PATHHOME等变量可能非常精简。务必在脚本中设置所需环境变量或使用命令的绝对路径。错误日志通常会发送给系统用户(或配置的MAILTO用户)。

  5. 时区问题:

    • Cron表达式的执行时间依赖于运行cron服务的操作系统的时区设置。确保服务器时区配置正确(如UTC或所需的本地时区)。在Spring应用中,可以通过@Scheduled(cron="...", zone="Asia/Shanghai")指定时区。

  6. 闰秒:

    • Cron通常不考虑闰秒。任务调度基于系统时钟,系统如何处理闰秒取决于操作系统和硬件。

  7. 启动与关闭:

    • 修改Crontab文件后需要重启cron服务(如sudo systemctl restart cronsudo service crond restart)才能生效(部分系统会自动重载,但重启更保险)。

    • 在Spring Boot应用中,修改@Scheduled的cron表达式通常需要重启应用。

  8. 权限问题:

    • 编辑系统级crontab (/etc/crontab 或 /etc/cron.d/ 下的文件)需要root权限。

    • 用户级crontab (crontab -e) 编辑的是当前用户的任务。

    • 确保cron任务运行的用户有权限执行相应的命令或访问所需的文件。

  9. 资源消耗与并发:

    • 非常高频(如每秒)的任务需谨慎,避免对系统造成过大负担。

    • 注意任务执行时间可能重叠(如果前一个任务还没结束,下一个又开始了)。Spring的@Scheduled默认是单线程执行,任务会排队。Quartz可以配置线程池和并发策略。


六、工具推荐:验证与生成你的Cron表达式

不要手动硬猜!善用工具:

  1. 在线验证/生成器 (强烈推荐!):

  2. IDE 插件:

    • IntelliJ IDEA / VSCode 等可能有cron表达式提示和验证插件。

  3. 代码中验证 (Spring/Quartz):

    • Spring的CronExpression类 (org.springframework.scheduling.support.CronExpression) 可以用于解析和验证表达式有效性。

    • Quartz的CronExpression类 (org.quartz.CronExpression) 同样提供验证功能。


七、总结

掌握cron表达式是自动化运维和开发的必备技能。理解其7字段结构、熟练掌握特殊字符(* ? , - / L W #) 的含义、牢记不同系统(特别是Linux Crontab vs Spring/Quartz)的关键差异,并利用在线工具进行验证和生成,是写出正确、高效定时任务计划的关键。

希望这份大全能成为你案头的终极参考!收藏本文,定时任务无忧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿Mr.wu

你的鼓励师我创造最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值