Golang 啟停管理及後臺執行

MexChina發表於2020-03-20

每當用 golang 編譯好程式進行工程化部署的時候,在不使用容器的情況下,我們如果要想使編譯後的可執行程式進行服務化的執行,我們一般都是採用 nohup 的方式,或者藉助於其他語音編寫的指令碼管理器。golang 作為強大的工程語言,自身問題還是自身解決的好。

封裝一個 cmd 的類:

package cmd

import (
    "fmt"
    "github.com/spf13/cobra"
    "io/ioutil"
    "os"
    "os/exec"
    "path/filepath"
    "strings"
)

//function 函式型別
type function func(environment, output, version string, debug bool)

//Run 啟動命令
func Run(version string, start function) {
    dir, err := filepath.Abs(filepath.Dir(os.Args[0])) 
    if err != nil {
        panic(err)
    }
    appName := strings.TrimLeft(os.Args[0], "./")
    bin := fmt.Sprintf("%s/%s", dir, appName)
    rootCmd := &cobra.Command{
        Use:  appName,
        Long: fmt.Sprintf("%s Version %s, for Linux (x86_64) \nCopyright (c) 2020.\n", bin, version),
    }

    var daemon, debug bool
    var environment, output, arg string

    startCmd := &cobra.Command{
        Use:   "start",
        Short: fmt.Sprintf("Start %s service", appName),
        Run: func(cmd *cobra.Command, args []string) {

            if daemon {
                if debug {
                    arg = "--debug"
                } else {
                    arg = ""
                }
                command := exec.Command(bin, "start", "-e", environment, "-l", output, arg)
                err := command.Start()
                if err != nil {
                    panic(err)
                }

                fmt.Printf("%s start, [PID] %d running...\n", bin, command.Process.Pid)
                err = ioutil.WriteFile(fmt.Sprintf("./%s.lock", appName), []byte(fmt.Sprintf("%d", command.Process.Pid)), 0666)
                if err != nil {
                    panic(err)
                }
                daemon = false
                os.Exit(0)
            } else {
                fmt.Printf("%s start\n", bin)
            }
            start(environment, output, version, debug)
        },
    }
    startCmd.Flags().StringVarP(&environment, "env", "e", "", "program running environment dev|test|pro")
    startCmd.Flags().StringVarP(&output, "log", "l", "./log", "program log folder")
    startCmd.Flags().BoolVarP(&daemon, "daemon", "d", false, "is daemon")
    startCmd.PersistentFlags().BoolVar(&debug, "debug", false, "program debug info")
    rootCmd.AddCommand(startCmd)

    rootCmd.AddCommand(&cobra.Command{
        Use:   "version",
        Short: fmt.Sprintf("Service %s version", appName),
        Run: func(cmd *cobra.Command, args []string) {
            fmt.Println(fmt.Sprintf("%s version %s", appName, version))
        },
    })

    rootCmd.AddCommand(&cobra.Command{
        Use:   "stop",
        Short: fmt.Sprintf("Stop %s service", appName),
        Run: func(cmd *cobra.Command, args []string) {
            pidByte, err := ioutil.ReadFile(fmt.Sprintf("./%s.lock", appName))
            if err != nil {
                fmt.Println(err.Error())
                return
            }

            command := exec.Command("kill", string(pidByte))
            err = command.Start()
            if err != nil {
                fmt.Print(err.Error())
            }
            fmt.Println(fmt.Sprintf("%s stop", bin))
        },
    })

    _ = rootCmd.Execute()
}

main 入口呼叫:

package main

import (
    "dashixiong/library/bootstrap"
    "dashixiong/library/cmd"
    "dashixiong/library/config"
    "dashixiong/library/logger"
    "dashixiong/sparring/route"
    "github.com/valyala/fasthttp"
)

func main() {

    cmd.Run("v0.1", func(environment, output, version string, debug bool) {

        cfg := config.Config{
            DEBUG:   debug,
            ENV:     environment,
            VERSION: version,
            LOG:output,
        }

        bootstrap.Start(cfg)
        err := fasthttp.ListenAndServe(":9042", route.InitRouter().Handler)
        if err != nil {
            logger.Error(err.Error())
        }
    })
}

編譯後啟停管理效果:

[root@dev bot]# ./bot 
/root/bot/bot Version v0.1, for Linux (x86_64) 
Copyright (c) 2020.

Usage:
  bot [command]

Available Commands:
  help        Help about any command
  start       Start bot service
  stop        Stop bot service
  version     Service bot version

Flags:
  -h, --help   help for bot

Use "bot [command] --help" for more information about a command.
[root@dev bot]# ./bot version
bot version v0.1
[root@dev bot]# ./bot start -h
Start bot service

Usage:
  bot start [flags]

Flags:
  -d, --daemon       is daemon
      --debug        program debug info
  -e, --env string   program running environment dev|test|pro
  -h, --help         help for start
  -l, --log string   program log folder (default "./log")
[root@dev bot]# ./bot start -e dev --debug -d -l /tmp/log 
/root/bot/bot start, [PID] 32413 running...
[root@dev bot]# ./bot stop
/root/bot/bot stop
[root@dev bot]# 

以後再也不用 nohup 了。

更多原創文章乾貨分享,請關注公眾號
  • Golang 啟停管理及後臺執行
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章