croncli 定时器命令(golang)

定时器是执行任务时的常用功能,配置系统的定时任务太麻烦,所以就想用golang简单实现一个定时器命令。

定时器的参数包括:

$ croncli -h
定时器命令

Usage:
  croncli [flags]

Flags:
  -c, --cron string     支持标准的crontab 表达式, ex. * * * * * *
                        各个 * 号的含义:
                        - 秒
                        - 分钟
                        - 小时
                        - 每月的第几天
                        - 月
                        - 每周的第几天
  -h, --help            help for croncli
  -m, --mode string     任务执行模式:
                        - delay(如果上一次任务还未执行完成(耗时太长),则等待上一次任务完成之后再执行)
                        - skip(如果上一次任务还未完成,则跳过此次执行)
      --norecover       是否捕获任务的 panic 错误, 默认 false
      --os string       系统类型,nx=linux win=windows,默认nx (default "nx")
  -r, --repeat string   重复规则, ex. 1s(每秒重复),1m(每分钟重复),1h(每小时重复)

其中控制执行时机的参数有2个:

  • -c, –corn 参数内容是crontab 表达式,之后的命令按照这个crontab
  • -r, –repeat 这个参数相当于cron参数的简化版,用来设置命令的重复执行

这2个参数同时使用的话,同时生效。也就是说,命令既重复执行,也按照crontab设置的规则执行。

另外,-m, –mode 参数只能是 delay 和 skip,含义参见上面的help说明。

对于单个命令,执行方式如下:(通过 Ctrl+C 结束程序运行)

$ croncli --repeat 2s date
- Press Ctrl+C to terminate
OUTPUT>>>>>
Wed 16 Mar 2022 10:45:08 AM CST

OUTPUT>>>>>
Wed 16 Mar 2022 10:45:10 AM CST

OUTPUT>>>>>
Wed 16 Mar 2022 10:45:12 AM CST

^Cinterrupt

上面的命令用 –repeat 参数,等价于下面的 –cron 参数:

$ croncli --cron "*/2 * * * * *" date
- Press Ctrl+C to terminate
OUTPUT>>>>>
Wed 16 Mar 2022 10:50:42 AM CST

OUTPUT>>>>>
Wed 16 Mar 2022 10:50:44 AM CST

OUTPUT>>>>>
Wed 16 Mar 2022 10:50:46 AM CST

^Cinterrupt

执行多个命令时,需要注意的是,多个命令要用单引号或者双引号括起来。

$ croncli --cron "*/2 * * * * *" "date; uname -r"
- Press Ctrl+C to terminate
OUTPUT>>>>>
Wed 16 Mar 2022 10:54:38 AM CST
5.10.0-10-amd64

OUTPUT>>>>>
Wed 16 Mar 2022 10:54:40 AM CST
5.10.0-10-amd64

OUTPUT>>>>>
Wed 16 Mar 2022 10:54:42 AM CST
5.10.0-10-amd64

^Cinterrupt

这里的 “date; uname -r” 要用 双引号括起来,如果没有这个双引号,就变成2个命令,
一个是 croncli –cron “/2 * * ” date,一个是 uname -r

首先编译一个windows下的可执行文件。

GOOS=windows GOARCH=amd64 go build

然后执行:

D:\share>croncli.exe -r 2s --os win echo %date%
- Press Ctrl+C to terminate
OUTPUT>>>>>
2022/03/17

OUTPUT>>>>>
2022/03/17

OUTPUT>>>>>
2022/03/17

OUTPUT>>>>>
2022/03/17

interrupt

执行的命令中出现崩溃错误是,如果不处理,会导致整个定时器停止,比如:

$ croncli -r 2s --norecover cat file-not-existed
- Press Ctrl+C to terminate
panic: exit status 126

goroutine 34 [running]:
main.CmdJob.Run({{0x592e82, 0x2}, {0xc0000b40f0, 0x2, 0x5}})
        /home/wangyubin/projects/golang/croncli/cmdjob.go:22 +0xb3
github.com/robfig/cron/v3.(*Cron).startJob.func1()
        /home/wangyubin/projects/gopath/pkg/mod/github.com/robfig/cron/v3@v3.0.0/cron.go:307 +0x6a
created by github.com/robfig/cron/v3.(*Cron).startJob
        /home/wangyubin/projects/gopath/pkg/mod/github.com/robfig/cron/v3@v3.0.0/cron.go:305 +0xb2

默认不带 –norecover 参数时,命令崩溃这不会导致定时器的中止,比如:

$ croncli -r 2s  cat file-not-existed
- Press Ctrl+C to terminate
cron: 2022/03/17 00:52:40 panic, error=exit status 126, stack=...

goroutine 22 [running]:
github.com/robfig/cron/v3.Recover.func1.1.1()
        /home/wangyubin/projects/gopath/pkg/mod/github.com/robfig/cron/v3@v3.0.0/chain.go:45 +0x85
panic({0x587da0, 0xc000024040})
        /usr/local/go/src/runtime/panic.go:1038 +0x215
main.CmdJob.Run({{0x592e82, 0x2}, {0xc0000c2040, 0x2, 0x4}})
        /home/wangyubin/projects/golang/croncli/cmdjob.go:22 +0xb3
github.com/robfig/cron/v3.Recover.func1.1()
        /home/wangyubin/projects/gopath/pkg/mod/github.com/robfig/cron/v3@v3.0.0/chain.go:53 +0x73
github.com/robfig/cron/v3.FuncJob.Run(0x0)
        /home/wangyubin/projects/gopath/pkg/mod/github.com/robfig/cron/v3@v3.0.0/cron.go:131 +0x1a
github.com/robfig/cron/v3.(*Cron).startJob.func1()
        /home/wangyubin/projects/gopath/pkg/mod/github.com/robfig/cron/v3@v3.0.0/cron.go:307 +0x6a
created by github.com/robfig/cron/v3.(*Cron).startJob
        /home/wangyubin/projects/gopath/pkg/mod/github.com/robfig/cron/v3@v3.0.0/cron.go:305 +0xb2
cron: 2022/03/17 00:52:42 panic, error=exit status 126, stack=...

goroutine 5 [running]:
github.com/robfig/cron/v3.Recover.func1.1.1()
        /home/wangyubin/projects/gopath/pkg/mod/github.com/robfig/cron/v3@v3.0.0/chain.go:45 +0x85
panic({0x587da0, 0xc0000241a0})
        /usr/local/go/src/runtime/panic.go:1038 +0x215
main.CmdJob.Run({{0x592e82, 0x2}, {0xc0000c2040, 0x2, 0x4}})
        /home/wangyubin/projects/golang/croncli/cmdjob.go:22 +0xb3
github.com/robfig/cron/v3.Recover.func1.1()
        /home/wangyubin/projects/gopath/pkg/mod/github.com/robfig/cron/v3@v3.0.0/chain.go:53 +0x73
github.com/robfig/cron/v3.FuncJob.Run(0x0)
        /home/wangyubin/projects/gopath/pkg/mod/github.com/robfig/cron/v3@v3.0.0/cron.go:131 +0x1a
github.com/robfig/cron/v3.(*Cron).startJob.func1()
        /home/wangyubin/projects/gopath/pkg/mod/github.com/robfig/cron/v3@v3.0.0/cron.go:307 +0x6a
created by github.com/robfig/cron/v3.(*Cron).startJob
        /home/wangyubin/projects/gopath/pkg/mod/github.com/robfig/cron/v3@v3.0.0/cron.go:305 +0xb2
^Cinterrupt

虽然命令因为错误崩溃,定时器仍然会定时重新执行命令,直到主动使用 Ctrl+C 来退出。

还有一种异常的情况时,如果命令执行时间过长,也就是这次的命令还没执行完,却已经到了下次命令的执行的时间。

这时,我们可以通过 –mode 参数控制下次命令的执行。
一种是让下次命令等待这次命令执行完再执行(–mode delay),这样就会导致后续所有的命令都延迟执行,比如:

$ croncli -r 2s --mode delay "date; sleep 3"
- Press Ctrl+C to terminate
OUTPUT>>>>>
Thu 17 Mar 2022 01:10:04 AM CST

OUTPUT>>>>>
Thu 17 Mar 2022 01:10:07 AM CST

OUTPUT>>>>>
Thu 17 Mar 2022 01:10:10 AM CST

^Cinterrupt

所有的命令都等上一个执行完(需要3秒)才执行,所以命令执行间隔是3秒。

还有一种情况是忽略这次的命令执行(–mode skip),比如:

$ croncli -r 2s --mode skip "date; sleep 3"
- Press Ctrl+C to terminate
OUTPUT>>>>>
Thu 17 Mar 2022 01:11:56 AM CST

OUTPUT>>>>>
Thu 17 Mar 2022 01:12:00 AM CST

OUTPUT>>>>>
Thu 17 Mar 2022 01:12:04 AM CST

^Cinterrupt

由于每次命令执行需要3秒,所以这个命令的下一个命令(间隔2s)都忽略执行了,只有下下个命令(间隔4s)才能轮到执行。

这只是初步实现的定时器,后续可以继续改进,比如:

Original: https://www.cnblogs.com/wang_yb/p/16015652.html
Author: wang_yb
Title: croncli 定时器命令(golang)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/516394/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • go-micro集成链路跟踪的方法和中间件原理

    前几天有个同学想了解下如何在go-micro中做链路跟踪,这几天正好看到wrapper这块,wrapper这个东西在某些框架中也称为中间件,里边有个opentracing的插件,正…

    Go语言 2023年5月25日
    058
  • go实用编程-算法篇 -归并排序

    /**** // i: the begin index of old sub-array, j: the begin index of even sub-array | array…

    Go语言 2023年5月25日
    070
  • Go – 使用 sync.WaitGroup 来实现并发操作

    如果你有一个任务可以分解成多个子任务进行处理,同时每个子任务没有先后执行顺序的限制,等到全部子任务执行完毕后,再进行下一步处理。这时每个子任务的执行可以并发处理,这种情景下适合使用…

    Go语言 2023年5月25日
    060
  • 【CGO】C源码编译为动态库供go程序调用(linux环境、arm架构运行平台)

    动态库编译 1.安装并配置交叉编译工具链网上有详细教程 2.go env环境配置 go env -w CGO_ENABLED=1 go env -w GOOS=linux go e…

    Go语言 2023年5月25日
    052
  • Go语言程序记录日志

    许多软件系统运行中需要日志文件。Go语言程序中,输出日志需要使用包”log”,编写程序十分简单。 像Java语言程序,输出日志时,往往需要使用开源的软件包来…

    Go语言 2023年5月29日
    038
  • Go – 如何编写 ProtoBuf 插件 (三) ?

    上篇文章《Go – 如何编写 ProtoBuf 插件 (二) 》,分享了基于 自定义&#x90…

    Go语言 2023年5月25日
    063
  • GO的URL合法性检查

    原文连接:https://www.zhoubotong.site/post/67.html Go 标准库的net/url包提供的两个函可以直接检查URL合法性,不需要手动去正则匹配…

    Go语言 2023年5月25日
    079
  • websocket:二.Golang实现Websocket消息通知

    我们在设计产品的时候通常都会遇到消息通知的时候,比如用户下单支付成功,比如用户有站内信来可以实时通知。而http是单向的,客户端请求,服务端返回,这次请求就已经结束。而websoc…

    Go语言 2023年5月25日
    060
  • day2-变量与数据类型

    变量 概念:程序的基本组成单位 定义: 指定变量类型 根据值自行判断变量类型(类型推导) 省略var,定义赋值 var i int var i = 10 i, j := 20, 1…

    Go语言 2023年5月25日
    059
  • install go 环境

    GoSDK安装 下载 GO SDK wget https://golang.google.cn/dl/go1.17.3.linux-amd64.tar.gz tar xfv go1…

    Go语言 2023年5月25日
    046
  • Golang使用swaggo自动生成Restful API文档

    相信很多程序猿和我一样不喜欢写API文档。写代码多舒服,写文档不仅要花费大量的时间,有时候还不能做到面面具全。但API文档是必不可少的,相信其重要性就不用我说了,一份含糊的文档甚至…

    Go语言 2023年5月25日
    056
  • go-micro使用Consul做服务发现的方法和原理

    go-micro v4默认使用mdns做服务发现。不过也支持采用其它的服务发现中间件,因为多年来一直使用Consul做服务发现,为了方便和其它服务集成,所以还是选择了Consul。…

    Go语言 2023年5月25日
    085
  • 紫色飞猪的研发之旅–06go自定义状态码

    在实际开发中,需要前后端需要协商状态码,状态码用于后端返前端时使用。在一个团队中,定义的状态码讲道理应该是一致的,项目开始的起始阶段状态码应该是定义了个七七八八的,随着功能的叠加而…

    Go语言 2023年5月25日
    064
  • Go语言之结构体与方法

    结构体是一系列属性的集合(类似于 Python 中的类) 1、结构体的定义与使用 // 定义 type Person struct { Name string Age int Se…

    Go语言 2023年5月25日
    063
  • 流量管制-令牌桶与漏桶

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Go语言 2023年5月25日
    056
  • Go语言之高级篇beego框架之controller调用model

    一、controller调用model 开发规范,就该把对数据库的操作写在model文件夹中。 示例: views/main.go routers/router.go models…

    Go语言 2023年5月29日
    063
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球