当涉及自动化任务和定时执行时,CRON 是一个强大的工具。CRON 允许你在预定的时间间隔内自动运行脚本、命令或任务,无需手动干预。在本文中,我们将深入探讨基于定时 CRON 的自动化任务,介绍如何设置和管理定时任务,以及一些常见的用例。
什么是 cron
CRON 是一个在类 Unix 操作系统中用于自动化任务调度的工具。它使用一种简单的语法来定义任务运行的时间间隔,可以精确到分钟、小时、日期等。通过使用 CRON,你可以编排和管理重复性的任务,从而减少手动操作的需求。
简单的来说 cron 作用是用来描述任务执行执行时机。
CRON 表达式
CRON 表达式是一个包含五个或六个字段的字符串,用于定义任务的执行时间。这些字段分别表示分钟、小时、日期、月份和星期几。
Cron表达式是一个字符串,通常字符串由6个域或者7个域构成,每一个域代表一个含义
语法格式:
- 7 个域: 秒、分、时 、月天、月、周天、年
- 6 个域:秒、分、时、月天、月、周天
- 5 个域: 分、时、月天、月、周天
CRON 应用场景
CRON 表达式域的取值
域 | 允许值 | 允许特殊字符 |
---|---|---|
秒 | 0-59 | ,-* / |
分 | 0-59 | ,-* / |
时 | 0-23 | ,-* / |
日 | 1-31 | ,-* / ? L W |
月 | 1-12 | ,-* / |
周 | 1-7 | ,-* / ? L # |
年 | 1970-2099 | ,-* / |
Cron 字符描述
*
: 代表所有可能的值,-
: 代表指定范围,
: 代表列举出枚举值,比如在分钟子表达式中,“5,20” 表示在第 5 分钟和第 20 分钟出发/
: 表示指定增量,比如在分钟子表达式中,“0/15” 表示从第 0 分钟开始,每 15 分钟执行一次,“3/20” 表示从第 3 分钟开始,每 20 分钟执行一次?
:主要用于月天或者周天中,指“没有具体的值”,当两个子表达式其中一个被指定了值以后,为了避免冲突,需要将另外一个值设置为 ?。比如想在每月 20 日出发调度,不管 20 号是星期几,只能用如下的写法:0 0 0 20 * ? ,其中最后一位只能用 ? ,而不能用 *L
: 主要用于月天或者周天中,在周天中, L 表示一个星期的最后一天,也就是 7 或者 SAT,在月天中,L 表示一个月的最后一天,比如 1 月 31 号,或者 2 月 28 号,或者 3 月 30 号。如果 L 前有具体的内容,那么就有其他含义,比如 6L 表示这个月的倒数第六天#
:只能用在周天中
CRON 示例
* * * * ? # 每分钟触发一次
0 0 * * * ? # 每天每1小时触发一次
0 0 10 * * ? # 每天10点触发一次
0 * 14 * * ? # 在每天下午2点到下午2:59期间的每1分钟触发
0 30 9 1 * ? # 每月1号上午9点半
0 15 10 15 * ? # 每月15日上午10:15触发
*/5 * * * * ? # 每隔5秒执行一次
*/1 * * * * # 每隔 1 分钟执行一次
0 */1 * * * ? # 每隔1分钟执行一次
30 3,12 * * * # 每天凌晨三点半和十二点半执行
0 0 5-15 * * ? # 每天5-15点整点执行
0 0/3 * * * ? # 每三分钟执行一次
30 */6 * * * # 每六个半小时执行一次
0 0-5 14 * * ? # 在每天下午2点到下午2:05期间的每1分钟触发
0 0/5 14 * * ? # 在每天下午2点到下午2:55期间的每5分钟触发
0 0/5 14,18 * * ? # 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
0 0/30 9-17 * * ? # 朝九晚五工作时间内每半小时
30 8-18/2 * * * # 在每天的早上 8 点到下午 6 点之间间隔两个半小时执行一次
30 21 * * * # 在每天的晚上九点半执行一次
45 4 1,10,22 * * # 在每个月的第一、十、二十二天的凌晨四点四十五执行
10 1 * * 6,0 # 每周六日凌晨一点十分执行
0,30 18-23 * * * # 在每天的下午六点到十一点之间零点和半点执行
* 23,00-07/1 * * * # 每天的晚上二十三点和半夜零点和早上七点每隔一小时每分钟执行
0 0 10,14,16 * * ? # 每天上午10点,下午2点,4点
0 0 12 ? * WED # 表示每个星期三中午12点
0 0 17 ? * TUES,THUR,SAT # 每周二、四、六下午五点
0 10,44 14 ? 3 WED # 每年三月的星期三的下午2:10和2:44触发
0 15 10 ? * MON-FRI # 周一至周五的上午10:15触发
0 0 23 L * ? # 每月最后一天23点执行一次
0 15 10 L * ? # 每月最后一日的上午10:15触发
0 15 10 ? * 6L # 每月的最后一个星期五上午10:15触发
0 15 10 * * ? 2005 # 2005年的每天上午10:15触发
0 15 10 ? * 6L 2002-2005 # 2002年至2005年的每月的最后一个星期五上午10:15触发
0 15 10 ? * 6#3 # 每月的第三个星期五上午10:15触发
Cron 在线测试工具
www.jsons.cn/quartzcheck…
任务调度原理
说到任务调度,我们需要了解一个算法,时间轮算法;时间轮算法,是一种实现定时器的巧妙算法,任务调度等各种框架中都有用到。
时间轮算法的设计其实就是来自于时钟;
时间轮算法实例
圆心位置表示的是当前的时间,随着时间推移, 圆心处的时间也会不断跳动。在计算机中时间轮的底层
就是一个环形链表,或者环形数组,每个元素都存放一个链表,链表中封装了很多定时任务;
时间轮执行任务流程
我只需要把任务放到它需要被执行的时刻,然后等着时针转到这个时刻时,取出该时刻放置的任务,执
行就可以了。对于时间轮算法,主要的功能有4个 。1. 加入任务 2. 执行任务 3. 删除任务 4. 沿着时间刻
度前进;
对于这4个功能来说最复杂的功能就是加入任务。下面我们重点来讲解加入任务;
eg:初始的时候, 时间轮的指针定格在0。此时添加一个延迟时间为2s的任务, 那么这个任务将会插入到第
二个时间格中;当时间轮的指针指到第二个时间格就会触发任务;
如果这个时候又插入一个延时时间为8s的任务进来, 这个任务的触发时间就是在当前时间2s的基础上加
8s, 也就是10s, 那么这个任务将会插入到10s的时间格中。
"动态"时间轮
那么如果在当前时间是2s的时候, 插入一个延时时间为19s的任务时,这个任务的触发时间就是在当前时
间 2s的基础上加19s, 也就是21s,在我们的时间轮上是没有21s的时间格的;这个任务将会插入到过期
时间为1s的 时间格中。为什么呢?
时间轮升级
如果在当前时间是2s的时候, 插入一个延时时间为22s的任务, 这个任务的触发时间就是在2s的基础上加
22s,也就是24s。
显然当前时间轮是无法找到过期时间格为24秒的时间格,因为当前过期时间最大的时间格才到21s。而
且我们也没办法像前面那样再复用时间格,其他的时间格都还没过期呢。当前时间轮无法承载这个定时
任务,那么应该怎么办呢?
层级时间轮
第二层时间轮也是由20个时间格组成, 每个时间格的跨度是20s。图中展示了每个时间格对应的过期时间
范围, 我们可以清晰地看到, 第二层时间轮的第0个时间格的过期时间范围是 [0,19]。也就是说, 第二层时
间轮的一个时间格就可以表示第一层时间轮的所有(20个)时间格;
第一级的时间轮走一圈,第二级的时间轮走一格。
在当前时间是2s的时候, 插入一个延时时间为22s的任务,该任务触发时间时间为24s。当第一层时间轮
容纳不下时,进入第二层时间轮,并插入到过期时间为[20,39]的时间格中。
"动态"层级时间轮
当第一层时间轮的指针定格在1s时,超时时间0s的时间格就过期了。而这个时候,第二层时间轮第0个
时间格的时间范围就从[0,19]分为了过期的[0],和未过期的[1,19]。而过期的[0]就会被新的过期时间
[400]复用。
总结
CRON 是一个强大的工具,可以帮助你自动化重复性任务,提高效率并减少手动操作的需求。通过设置和管理定时 CRON 任务,你可以轻松实现各种自动化场景,从数据备份到系统监控,都可以通过 CRON 实现。务必仔细考虑任务的需求和影响,合理配置 CRON 表达式,确保任务按计划运行。