Golang:如何在二进制更新时自动重启进程?

时间:2016-12-29 08:49:04

标签: go deployment

我在本地构建golang应用程序,然后scp到服务器。我需要停止该过程并手动重启。有没有办法在二进制更新时自动重启进程?

4 个答案:

答案 0 :(得分:3)

虽然通常使用daemontools或类似工具在进程外实现这一点通常更好,但在某些情况下,您需要/需要在程序内部完成。

在程序中执行此操作可能会非常棘手,具体取决于程序特征,例如可能已打开的连接或文件等。

话虽如此,这里有一个适用于大多数情况的实现:

package main

import (
    "log"
    "os"
    "syscall"
    "time"

    "github.com/fsnotify/fsnotify"
    "github.com/kardianos/osext"
)

func setupWatcher() (chan struct{}, error) {
    file, err := osext.Executable()
    if err != nil {
        return nil, err
    }
    log.Printf("watching %q\n", file)
    w, err := fsnotify.NewWatcher()
    if err != nil {
        return nil, err
    }
    done := make(chan struct{})
    go func() {
        for {
            select {
            case e := <-w.Events:
                log.Printf("watcher received: %+v", e)
                err := syscall.Exec(file, os.Args, os.Environ())
                if err != nil {
                    log.Fatal(err)
                }
            case err := <-w.Errors:
                log.Printf("watcher error: %+v", err)
            case <-done:
                log.Print("watcher shutting down")
                return
            }
        }
    }()
    err = w.Add(file)
    if err != nil {
        return nil, err
    }
    return done, nil
}

func main() {
    log.Print("program starting")
    watcher, err := setupWatcher()
    if err != nil {
        // do something sensible
        log.Fatal(err)
    }
    // continue with app startup
    time.Sleep(100 * time.Minute) // just for testing
    // eventually you may need to end the watcher
    close(watcher) // this way you can
}

然后你做

% go build main.go     
% ./main
2016/12/29 14:15:06 program starting
2016/12/29 14:15:06 watching "/home/plalloni/tmp/v/main"

这里是你运行(在其他终端中)一些连续的“go build main.go”(“更新”正在运行的二进制文件)后产生的输出。

2016/12/29 14:15:32 watcher received: "/home/plalloni/tmp/v/main": CHMOD
2016/12/29 14:15:32 program starting
2016/12/29 14:15:32 watching "/home/plalloni/tmp/v/main"
2016/12/29 14:15:38 watcher received: "/home/plalloni/tmp/v/main": CHMOD
2016/12/29 14:15:38 program starting
2016/12/29 14:15:38 watching "/home/plalloni/tmp/v/main"

希望它有所帮助。

答案 1 :(得分:2)

它需要复杂吗?您可以让entr运行并在二进制更改时触发更新程序脚本。

http://entrproject.org/

e.g。

echo 'binary_path' | entr script.sh &

答案 2 :(得分:1)

我对此案有一个解决方案。

另见。 https://github.com/narita-takeru/cmdrevive

例如

cmdrevive ./htmls/ ".html$" (application) (arguments)

所以,这种情况适用。

cmdrevive "/(app path)" "(app filename)" (app full path) (arguments)

如果(应用程序文件名)更改了(应用程序路径)目录,则使用(参数)重新启动(应用程序完整路径)。

这个怎么样?

答案 3 :(得分:0)

您可以使用https://github.com/slayer/autorestart

package main

import "github.com/slayer/autorestart"

func main() {
    autorestart.StartWatcher()
    http.ListenAndServe(":8080", nil) // for example
}