前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Go 写一个类似 cron 的定时任务管理器

Go 写一个类似 cron 的定时任务管理器

作者头像
公众号-利志分享
发布2022-04-25 08:43:11
发布2022-04-25 08:43:11
28800
代码可运行
举报
文章被收录于专栏:利志分享利志分享
运行总次数:0
代码可运行
  1. 用 Go 写一个类似 cron 的定时任务管理器。这个任务可以通过 HTTP API 去 添加/删除任务。
  2. 用 go 标准库,不用第三方库。
  3. go 不熟悉的话,用任何你熟悉的后端语言
目标

● 通过命令行启动启动服务

代码语言:javascript
代码运行次数:0
运行
复制
// 第一个命令行参数指定监听端口 $ ./gocron 4567
GoCron listening on 4567

● 创建新的任务

代码语言:javascript
代码运行次数:0
运行
复制
// 每 5 秒钟执行一次 date -R
// 子进程的输出直接用服务进程的标准输出即可
// 服务返回 HTTP 200:
{ ”ok”: true, ”id”: ”print-time”}
// 任务以存在,服务返回 HTTP 409:
{ ”ok”: false, ”error”: ”The task print-time already exists.”}// 用 JSON POST 去创建任务 curl -X POST localhost:4567 -d '
{
"id": "print-time", "cmd": "date", "args": ["-R"], "interval": 5000
}
'
// 每 5 秒钟执行一次 date -R
// 子进程的输出直接用服务进程的标准输出即可 // 服务返回 HTTP 200:
{ "ok": true, "id": "print-time"}
// 任务以存在,服务返回 HTTP 409:
{ "ok": false, "error": "The task print-time already exists."}

● 终止定时任务

代码语言:javascript
代码运行次数:0
运行
复制
// 服务返回, HTTP 200:
{ ”ok”: true, ”id”: ”print-time”}
// 没有该任务的话, HTTP 404:
{ ”ok”: false, ”error”: ”The task print-time is not found.”}curl -X DELETE localhost:4567 -d '
{
"id": "print-time",
} '
// 服务返回, HTTP 200:
{ "ok": true, "id": "print-time"}
// 没有该任务的话, HTTP 404:
{ "ok": false, "error": "The task print-time is not found."}

下面是答案——————

代码语言:javascript
代码运行次数:0
运行
复制
package main

import (
    "bufio"
    "encoding/json"
    "fmt"
    "io"
    "io/ioutil"
    "log"
    "net/http"
    "os"
    "os/exec"
    "time"
    //"runtime/debug"
)

var Debug = true
var tickMaps = make(map[string]*time.Timer)

type BodyJson struct {
    Id       string
    Cmd      string
    Args     []string
    Interval time.Duration
}

type DBodyJson struct {
    Id string
}

func newTimer(id string, cmd string, args []string, interval time.Duration) {
    tickMaps[id] = time.NewTimer(time.Millisecond * interval)
    for {
        select {
        case <-tickMaps[id].C:
            tCmd := exec.Command(cmd, args...)
            stdout, err := tCmd.StdoutPipe()
            if err != nil {
                fmt.Println(err)
                break
            }
            tCmd.Start()
            reader := bufio.NewReader(stdout)
            for {
                line, err2 := reader.ReadString('\n')
                if err2 != nil || io.EOF == err2 {
                    break
                }
                fmt.Println(line)
            }
            tCmd.Wait()
            fmt.Println(8888)
            tickMaps[id].Reset(time.Millisecond * interval)
        }
    }
}

func HelloWorld(w http.ResponseWriter, r *http.Request) {
    fmt.Println(r.Method)
    if r.Method == "POST" {
        body, err := ioutil.ReadAll(r.Body)
        if err != nil {
            fmt.Printf("read body err, %v\n", err)
            return
        }
        var tbody BodyJson
        if err = json.Unmarshal(body, &tbody); err != nil {
            fmt.Printf("Unmarshal err, %v\n", err)
            return
        }
        id := tbody.Id
        cmd := tbody.Cmd
        args := tbody.Args
        interval := tbody.Interval

        if tickMaps[id] == nil {
            go newTimer(id, cmd, args, interval)
            data := map[string]interface{}{"id": id, "ok": true}
            d, _ := json.Marshal(data)
            w.Header().Set("Content-Type", "text/json")
            w.Write([]byte(d))
        } else {
            data := map[string]interface{}{"error": "this " + id + "already exists.", "ok": false}
            d, _ := json.Marshal(data)
            w.Header().Set("Content-Type", "text/json")
            w.Write([]byte(d))
        }
    } else if r.Method == "DELETE" {
        body, err := ioutil.ReadAll(r.Body)
        if err != nil {
            fmt.Printf("read body err, %v\n", err)
            return
        }
        var tbody DBodyJson
        if err = json.Unmarshal(body, &tbody); err != nil {
            fmt.Printf("Unmarshal err, %v\n", err)
            return
        }
        id := tbody.Id
        if tickMaps[id] != nil && tickMaps[id].Stop() {
            data := map[string]interface{}{"id": id, "ok": true}
            d, _ := json.Marshal(data)
            w.Header().Set("Content-Type", "text/json")
            w.Write([]byte(d))
        } else {
            data := map[string]interface{}{"error": "this " + id + "not found", "ok": false}
            d, _ := json.Marshal(data)
            w.Header().Set("Content-Type", "text/json")
            w.Write([]byte(d))
        }
    }
}

func main() {
    //debug.PrintStack()

    if len(os.Args) != 2 {
        fmt.Println("no port param")
        return
    }
    port := os.Args[1]

    http.HandleFunc("/", HelloWorld)

    fmt.Println("GoCron listening on " + port)
    err := http.ListenAndServe(":"+port, nil)
    if err != nil {
        log.Fatal("ListenAndServe:", err)
        return
    }

}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-05-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 利志分享 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目标
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档