我在本地构建golang应用程序,然后scp
到服务器。我需要停止该过程并手动重启。有没有办法在二进制更新时自动重启进程?
答案 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
运行并在二进制更改时触发更新程序脚本。
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
}