我正在用Go编写服务器应用程序,并使用包装程序将其作为Windows服务运行。
有必要正常关闭服务器(以正确关闭资源和连接),在UNIX中,它将通过SIGTERM信号进行处理。没什么。
尽管在Windows上情况似乎大不相同。我在this guide上看到信号实际上存在于窗口(?)上,并且定义了SIGTERM,尽管其他页面指示they don't,或使用诸如WM_CLOSE之类的其他机制。
告诉无头程序正常终止的最佳方法是什么?该如何在Go中实现?
服务器被设计为多平台的,因此最好采用最标准的方式。
答案 0 :(得分:2)
答案 1 :(得分:1)
所以,过了一会儿,我只想分享我的解决方法。这很丑陋,但这是我发现的唯一真实方法。 Windows golang程序确实会侦听CTRL + C,这不是一个信号或类似的信号,但是它会使用与UNIX相同的信号触发go程序中的正常关机。
以下是相关代码:
// Create shutdown channel
exitChan := make(chan int)
interruptChan := make(chan os.Signal, 1)
signal.Notify(interruptChan, os.Interrupt)
select {
case exitCode := <-exitChan:
os.Exit(exitCode)
case <-interruptChan:
// This works in Windows if ctrl-c is invoked. It sucks though
svr.Stop()
os.Exit(-1)
}
要触发给定进程的CTRL + C,我使用了一个名为windows-kill.exe的小程序。
// Windows is "special" and we need to use a library for killing processes gracefully
// Unfortunately setting up the C++ library with go is a hassle, so we resort to a CLI tool
ex, _ := os.Executable()
cmdPath := filepath.Join(filepath.Dir(ex), "windows-kill.exe")
cmd := exec.CommandContext(context.Background(), cmdPath, "-SIGINT", strconv.Itoa(l.proc.Pid))
err := cmd.Start()
if err != nil {
panic(err)
}
这是库和工具的仓库:https://github.com/alirdn/windows-kill
答案 2 :(得分:1)
在Windows上使用* nix构造和函数的想法通常是不好的,并且容易产生奇怪的诡计,这些诡计可能有效也可能无效。
关闭GUI应用程序时清除的正确方法是处理WM_QUERYENDSESSION和WM_ENDSESSION。 另外,您在通用关闭机制上具有灵活性,请检查here。
如果您是服务,则获得通知的正确方法是控制台应用程序的服务处理程序(SERVICE_STOPPED)。有关更多信息,请参见Writing a ServiceMain。
答案 3 :(得分:0)
如果您正在运行某种形式的Web服务,则最好使用Web服务本身来启动关闭,因为跟踪信号的PIDS可能会变得混乱。
要停止http网络服务,只需添加以下路由:
http.HandleFunc("/shutdown",
func(w http.ResponseWriter, r *http.Request) {
// stops server - may want to add admin credentials check here!
srv.Shutdown(context.Background())
})
操场source-code示例。
2019/03/10 16:58:15 Listening on: :8080
$ curl 'localhost:8080/shutdown'
2019/03/10 17:04:17 Listening on: :8080
2019/03/10 17:04:19 exited cleanly