如何编写排除每月最后一个周一的Cron表达式
如何编写排除每月最后一个周一的Cron表达式
嘿,我来帮你搞定这个调度需求!看起来你想要让任务在每月的每个周一凌晨00:05自动运行,但得跳过当月的最后一个周一对吧?我分两种场景给你具体方案:
一、使用支持扩展语法的Cron(比如Quartz调度框架)
如果你的调度系统支持Quartz风格的扩展Cron语法,直接用表达式就能实现需求:
0 5 0 ? * MON#1-MON#4
或者更灵活的方式:先设置基础触发规则为所有周一00:05,再配合调度器的排除规则,跳过MON#L(代表当月最后一个周一)的触发。
语法说明:
0 5 0:对应凌晨00:05(Quartz的Cron顺序是秒 分 时,所以秒设为0,分是5,时是0)?:表示不指定具体日期(因为我们用周几来触发任务)MON#1-MON#4:明确指定运行每个月的第1到第4个周一(一个月最多有5个周一,这样就自动排除了最后一个)
二、标准Linux Cron(无扩展语法)
标准Linux Cron本身没有直接的“排除最后一个周一”的语法,我们可以结合Shell脚本做日期判断,再通过Cron调用脚本:
步骤1:编写判断脚本(比如命名为run_job.sh)
#!/bin/bash # 判断当天是否为当月最后一个周一 next_monday=$(date -d "$(date +%Y-%m-01) +$(( ( $(date +%u) % 7 ) + 7 )) days" +%Y-%m-%d) current_month=$(date +%m) next_month=$(date -d "$next_monday" +%m) if [ "$current_month" -eq "$next_month" ]; then # 下一个周一仍在当前月,说明今天不是最后一个周一,执行任务 echo "[$(date +%Y-%m-%d %H:%M:%S)] 开始执行任务..." # 在这里写入你的具体任务命令 else # 下一个周一进入下个月,说明今天是最后一个周一,跳过任务 echo "[$(date +%Y-%m-%d %H:%M:%S)] 跳过任务:今日是当月最后一个周一" fi
步骤2:设置Cron表达式
让Cron在每周一凌晨00:05调用这个脚本,同时记录日志:
5 0 * * 1 /path/to/run_job.sh >> /var/log/monthly_job.log 2>&1
脚本逻辑验证
拿你提到的例子来说:某个月的周一分别是3号、10号、17号、24号
- 3号、10号、17号的下一个周一都在当月,脚本会正常执行任务
- 24号的下一个周一已经是下个月的1号,脚本会自动跳过这次运行,完全符合你的预期!
备注:内容来源于stack exchange,提问作者Brijesh Cg Cg




