简介
cron
一个用于管理定时任务的库,用 Go 实现 Linux 中crontab
这个命令的效果。之前我们也介绍过一个类似的 Go 库——gron
。gron
代码小巧,用于学习是比较好的。但是它功能相对简单些,并且已经不维护了。如果有定时任务需求,还是建议使用cron
。
快速使用
文本代码使用 Go Modules。
创建目录并初始化:
$ mkdir cron && cd cron
$ go mod init github.com/darjun/go-daily-lib/cron
安装cron
,目前最新稳定版本为 v3:
$ go get -u github.com/robfig/cron/v3
使用:
package main
import (
"fmt"
"time"
"github.com/robfig/cron/v3"
)
func main() {
c := cron.New()
c.AddFunc("@every 1s", func() {
fmt.Println("tick every 1 second")
})
c.Start()
time.Sleep(time.Second * 5)
}
使用非常简单,创建cron
对象,这个对象用于管理定时任务。
调用cron
对象的AddFunc()
方法向管理器中添加定时任务。AddFunc()
接受两个参数,参数 1 以字符串形式指定触发时间规则,参数 2 是一个无参的函数,每次触发时调用。@every 1s
表示每秒触发一次,@every
后加一个时间间隔,表示每隔多长时间触发一次。例如@every 1h
表示每小时触发一次,@every 1m2s
表示每隔 1 分 2 秒触发一次。time.ParseDuration()
支持的格式都可以用在这里。
调用c.Start()
启动定时循环。
注意一点,因为c.Start()
启动一个新的 goroutine 做循环检测,我们在代码最后加了一行time.Sleep(time.Second * 5)
防止主 goroutine 退出。
运行效果,每隔 1s 输出一行字符串:
$ go run main.go
tick every 1 second
tick every 1 second
tick every 1 second
tick every 1 second
tick every 1 second
时间格式
与Linux 中crontab
命令相似,cron
库支持用 5 个空格分隔的域来表示时间。这 5 个域含义依次为:
Minutes
:分钟,取值范围[0-59]
,支持特殊字符* / , -
;Hours
:小时,取值范围[0-23]
,支持特殊字符* / , -
;Day of month
:每月的第几天,取值范围[1-31]
,支持特殊字符* / , - ?
;Month
:月,取值范围[1-12]
或者使用月份名字缩写[JAN-DEC]
,支持特殊字符* / , -
;Day of week
:周历,取值范围[0-6]
或名字缩写[JUN-SAT]
,支持特殊字符* / , - ?
。
注意,月份和周历名称都是不区分大小写的,也就是说SUN/Sun/sun
表示同样的含义(都是周日)。
特殊字符含义如下:
*
:使用*
的域可以匹配任何值,例如将月份域(第 4 个)设置为*
,表示每个月;/
:用来指定范围的步长,例如将小时域(第 2 个)设置为3-59/15
表示第 3 分钟触发,以后每隔 15 分钟触发一次,因此第 2 次触发为第 18 分钟,第 3 次为 33 分钟。。。直到分钟大于 59;,
:用来列举一些离散的值和多个范围,例如将周历的域(第 5 个)设置为MON,WED,FRI
表示周一、三和五;-
:用来表示范围,例如将小时的域(第 1 个)设置为9-17
表示上午 9 点到下午 17 点(包括 9 和 17);?
:只能用在月历和周历的域中,用来代替*
,表示每月/周的任意一天。
了解规则之后,我们可以定义任意时间:
30 * * * *
:分钟域为 30,其他域都是*
表示任意。每小时的 30 分触发;30 3-6,20-23 * * *
:分钟域为 30,小时域的3-6,20-23
表示 3 点到 6 点和 20 点到 23 点。3,4,5,6,20,21,22,23 时的 30 分触发;0 0 1 1 *
:1(第 4 个) 月 1(第 3 个) 号的 0(第 2 个) 时 0(第 1 个) 分触发。
记熟了这几个域的顺序,再多练习几次很容易就能掌握格式。熟悉规则了之后,就能熟练使用crontab
命令了。
func main() {
c := cron.New()
c.AddFunc("30 * * * *", func() {
fmt.Println("Every hour on the half hour")
})
c.AddFunc("30 3-6,20-23 * * *", func() {
fmt.Println("On the half hour of 3-6am, 8-11pm")
})
c.AddFunc("0 0 1 1 *", func() {
fmt.Println("Jun 1 every year")
})
c.Start()
for {
time.Sleep(time.Second)
}
}