在Windows上优雅地终止进程

问题描述 投票:1回答:2

我正在Go中编写一个服务器应用程序,并使用包装器将其作为Windows服务运行。

需要优雅地关闭服务器(以正确关闭资源和连接),在UNIX中,它将通过SIGTERM信号处理。没什么大不了。

虽然在Windows上看起来很不一样。我在this guide上看到信号实际存在于windows(?)上,并且SIGTERM已定义,但其他页面表示they don't,或者使用其他机制,如WM_CLOSE。

告诉无头进程优雅终止的最佳方法是什么?如何在Go中实现?

服务器设计为多平台,因此最常用的标准方法是这样做。

windows go service process
2个回答
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

0
投票

go开始取消任务/服务的方法是使用context.Context包。

因此,如果您希望信号处理程序触发任务的context.Context关闭:

func registerSigHandler() context.Context {
        sigCh := make(chan os.Signal, 1)
        signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)

        rootCtx := context.Background()
        taskCtx, cancelFn := context.WithCancel(rootCtx)

        go func() {
                sig := <-sigCh
                log.Println("received signal:", sig)

                // let sub-task know to wrap up: cancel taskCtx
                cancelFn()
        }()

        return taskCtx
}

然后将返回的taskCtx传递给您的工作任务,以便进行监听。

select {
    case <-taskCtx.Done():
        // context was canceled
    default: // poll - rather than block in this example
}

游乐场source-code

输出:

2019/03/10 19:18:51 Worker PID: 33186
2019/03/10 19:18:51 Will terminate on these signals: interrupt terminated
2019/03/10 19:18:51 2019-03-10 19:18:51.018962 -0400 EDT m=+0.001727305
2019/03/10 19:18:52 2019-03-10 19:18:52.022782 -0400 EDT m=+1.005517010
2019/03/10 19:18:53 2019-03-10 19:18:53.019925 -0400 EDT m=+2.002630457

$ kill -INT 33186

2019/03/10 19:18:53 received signal: interrupt
2019/03/10 19:18:53 task context terminated reason: context canceled
2019/03/10 19:18:53 wrapping up task...
2019/03/10 19:18:53 workerTask() exited cleanly
2019/03/10 19:18:53 main exited cleanly

编辑:

我在Windows 10上测试了这个,当从同一个控制台发出Ctrl-C时会触发清理。不确定如何在Windows上外部发送信号 - 这可能是OP的原始问题。使用say killtask /F /PID 33186确实会在没有触发任何信号处理程序的情况下终止进程。

© www.soinside.com 2019 - 2024. All rights reserved.