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

I built the golang app in local, then scp to server. I need to stop the process and restart manually. Is there any way to auto-restart the process when binary updated?

Does it need to be sophisticated? You could have entr running and trigger an updater script when the binary changes.

http://entrproject.org/

e.g.

echo 'binary_path' | entr script.sh &

While this is generally better to be implemented off-process using something like daemontools or similar, there are some cases when you want/need it to be done inside your program.

Doing it inside your program can be tricky depending on the program characteristics such as connections or files it may have open, etc.

Having said that, here you have an implementation which would work in most cases:

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
", 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
}

Then you do

% 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"

And here the output it produced after you run (in other terminal) some successive "go build main.go" (which "updates" the running binary).

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"

Hope it helps.

I have a resolution about this case.

See also. https://github.com/narita-takeru/cmdrevive

example

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

So, this case applicable.

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

If (app filename) changed on (app path) directory, then restart (app full path) with (arguments).

How about this one?