• croncli 定时器命令(golang)


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

    通过这个简单的命令,可以定时或者重复的执行其他命令。
    小工具基于:https://github.com/robfig/cron/ 来实现的。
    小工具开源在: https://gitee.com/wangyubin/croncli

    定时器命令格式

    定时器的参数包括:

    $ 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系统下的使用

    首先编译一个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
    

    特殊情况处理

    定时命令执行出现panic

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

    $ 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)才能轮到执行。

    其他

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

    1. 支持脚本的定时执行
    2. 能够限制执行的次数
  • 相关阅读:
    Leetcode 811. Subdomain Visit Count
    Leetcode 70. Climbing Stairs
    Leetcode 509. Fibonacci Number
    Leetcode 771. Jewels and Stones
    Leetcode 217. Contains Duplicate
    MYSQL安装第三步报错
    .net 开发WEB程序
    JDK版本问题
    打开ECLIPSE 报failed to load the jni shared library
    ANSI_NULLS SQL语句
  • 原文地址:https://www.cnblogs.com/wang_yb/p/16015652.html
Copyright © 2020-2023  润新知