【问题标题】:How to run a job on a specific time every day?如何在每天的特定时间运行作业?
【发布时间】:2021-03-02 04:56:11
【问题描述】:

我想在每天晚上 9 点打印出do my job。如何在 Go 中执行此操作?

这是我目前所得到的:

timer := time.NewTimer(3 * time.Second)
for {
    now := time.Now()
    next := now.Add(time.Hour * 24)
    todayNine := time.Date(next.Year(), next.Month(), next.Day(), 9, 0, 0, 0, next.Location()).AddDate(0, 0, -1)
    todayFifteen := time.Date(next.Year(), next.Month(), next.Day(), 15, 0, 0, 0, next.Location()).AddDate(0, 0, -1)
    todayEnd := time.Date(next.Year(), next.Month(), next.Day(), 0, 0, 0, 0, next.Location()).AddDate(0, 0,  -1)
    if now.Before(todayNine) {
        timer.Reset(todayNine.Sub(now))
    } else if now.Before(todayFifteen) {
        timer.Reset(todayFifteen.Sub(now))
    } else if now.Before(todayEnd) {
        timer.Reset(todayEnd.Sub(now))
    }
    <- timer.C
    fmt.Println("do my job")
}

【问题讨论】:

  • 您可以使用 ticker 并检查小时部分 time.Now() 。但是如果您的服务有多个实例正在运行,那就会很棘手..您最终将每个实例都执行一次。
  • 我建议在 go 二进制文件之外使用不同的系统来启动作业。它可以是 cron 作业或 k8 cron。如果你想纯粹使用 go "ticker" 来做,应该使用
  • 您的操作系统可能有一种方法可以安排程序在您想要的特定时间定期运行。您使用的是什么操作系统?
  • 抱歉没有尽快回复,这是我的解决方案,请告诉我您的想法,谢谢!

标签: go time


【解决方案1】:

我会使用cron 包。 https://pkg.go.dev/github.com/robfig/cron

文档中的示例:

c := cron.New()
c.AddFunc("0 30 * * * *", func() { fmt.Println("Every hour on the half hour") })
c.AddFunc("@hourly",      func() { fmt.Println("Every hour") })
c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty") })
c.Start()
..
// Funcs are invoked in their own goroutine, asynchronously.
...
// Funcs may also be added to a running Cron
c.AddFunc("@daily", func() { fmt.Println("Every day") })
..
// Inspect the cron job entries' next and previous run times.
inspect(c.Entries())
..
c.Stop()  // Stop the scheduler (does not stop any jobs already running).

【讨论】:

  • 抱歉没有及时回复,这是我的解决方案,请告诉我你的想法,谢谢!
【解决方案2】:

我会探索操作系统级别或基础架构级别的系统以在这些时间触发执行(*nix 中的 Cron 作业,k8s 中的 Cron 等)

但是,如果您想纯粹使用 go 来实现,您可以尝试同时使用 tickerClock

package main

import (
    "context"
    "fmt"
    "os"
    "time"
    "os/signal"
)

func main() {
    ticker := time.NewTicker(time.Minute)
    done := make(chan bool)
    ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
    defer stop()
    go func() {
        for {
            select {
            case <-done:
                return
            case <-ticker.C:
                h, m, _ := time.Now().Clock()
                if m == 0 && (  h == 9 || h == 15 ) {
                    fmt.Printf("Doing the job")
                }
            }
        }
    }()

    <-ctx.Done()
    stop()
    done <- true
}

链接到plaground

【讨论】:

  • 如果你停止并重新运行服务器,它会重新启动票吗?所以在这种情况下使用ticker可能不准确,我用它来实现提醒。我更喜欢使用 crontab 并为这样的工作制作端点,因此为此运行一个脚本以命中端点,为您的 vm 制作白名单 ip
  • @Pocket 正如我在问题的答案和评论中提到的那样,在这种情况下,go 二进制文件之外的基础设施级别触发器将是理想的,但如果他们想纯粹使用 go 来执行此操作,无论出于何种原因一个可能的解决方案
  • 抱歉没有及时回复,这是我的解决方案,请告诉我你的想法,谢谢!
猜你喜欢
  • 2016-06-05
  • 2020-09-02
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-08
  • 1970-01-01
相关资源
最近更新 更多