如何编写每月14日后首个周六或第三个周六23:59执行的Cron任务
解决方案
首先纠正你原命令的逻辑错误:你的Cron表达式是59 23 * * 6(周六23:59),但后续判断date +%u -d tomorrow(明天的星期)等于6(周六),这意味着明天是周六,那今天就是周五,但Cron只在周六触发,所以这个条件永远不成立,你的任务根本不会执行。
针对你的需求(每月14日之后的首个周六 或 当月第三个周六的23:59执行任务),以下是两种更简洁可靠的写法:
写法一:基于日期匹配的清晰逻辑
直接计算出当月符合要求的两个周六日期,再判断当前日期是否匹配:
59 23 * * 6 TODAY=$(date +%Y-%m-%d); \ FIRST_SAT_AFTER_14=$(date -d "$(date +%Y-%m-15) +sat" +%Y-%m-%d); \ THIRD_SAT_OF_MONTH=$(date -d "$(date +%Y-%m-01) +2 weeks +sat" +%Y-%m-%d); \ if [ "$TODAY" = "$FIRST_SAT_AFTER_14" ] || [ "$TODAY" = "$THIRD_SAT_OF_MONTH" ]; then \ the task; \ fi
$(date +%Y-%m-15) +sat:计算当月15日及之后的第一个周六$(date +%Y-%m-01) +2 weeks +sat:计算当月第三个周六(1号加2周再加周六,等价于第一个周六加2周)
写法二:基于周数与日期的判断
如果你的系统date命令支持%W(当年周数),可以用周差判断:
59 23 * * 6 MONTH_FIRST_SAT_WEEK=$(date -d "$(date +%Y-%m-01) +sat" +%W); \ CURRENT_WEEK=$(date +%W); \ CURRENT_DAY=$(date +%d); \ if [ $((CURRENT_WEEK - MONTH_FIRST_SAT_WEEK)) -eq 0 ] && [ $CURRENT_DAY -ge 15 ]; then \ the task; \ elif [ $((CURRENT_WEEK - MONTH_FIRST_SAT_WEEK)) -eq 2 ]; then \ the task; \ fi
- 第一个条件:是当月第一个周六,且日期在15日及之后(即14日后的首个周六)
- 第二个条件:是当月第三个周六(第一个周六加2周)
写法三:纯Cron扩展表达式(限支持扩展语法的Cron实现)
如果你的Cron支持#(第N个星期几)和范围判断,比如某些商业系统或扩展Cron工具,可以直接写:
59 23 15-21 * 6#1,6#3
15-21 * 6#1:当月第一个周六且日期在15-21之间(即14日后的首个周六)6#3:当月第三个周六
注意:标准Vixie Cron(Linux默认)不支持#语法,仅部分扩展实现支持。
内容的提问来源于stack exchange,提问作者Sneak Ferrari
相关产品推荐
相关产品推荐

