如何配置用 Go 编写的 Windows 服务的失败操作?

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

我正在使用

golang.org/x/sys/windows/svc
包在 Go 中编写 Windows 服务。

到目前为止,一切都很顺利,而且很容易上手,我喜欢它。

我编写了一些自动更新功能,我希望服务在完成更新后自行重新启动。

我尝试生成一个进程,该进程将使用

SCM
重新启动服务,但它记录了一条错误消息,这似乎与在作为本地系统运行时尝试控制服务有关。

The service process could not connect to the service controller. 

更好/更简单的方法似乎是

os.Exit(1)
并将服务
Failure Actions
设置为
Restart on Failure
,效果非常好!

唯一的麻烦是,似乎没有使用 Go 以编程方式配置这些选项的功能。

我做了一些挖掘,看起来它们是通过将结构传递给

ChangeServiceConfig2
中的
advapi32.dll
来配置的 - 如何创建在崩溃时重新启动的服务

golang/sys/blob/master/windows/svc/mgr/config.go -

func updateDescription(handle windows.Handle, desc string) error

代码已经调用了

windows.ChangeServiceConfig2
,这是 DLL 调用的链接。

SERVICE_FAILURE_ACTIONS
结构的 Microsoft 文档位于此处

我无法弄清楚如何使用 Go 构建和传递该结构 - 有人有任何见解吗?

windows service go advapi32
2个回答
4
投票

经过here的一些指导,再加上阅读现有 Go Windows 服务接口的源代码,我想出了自己的答案,我将尝试在下面记录它。

有关使用 Windows DLL 时的类型参考,MSDN 文档位于此处

我的代码如下所示:

import (
    "unsafe"
    "golang.org/x/sys/windows"
)

const (
    SC_ACTION_NONE                      = 0
    SC_ACTION_RESTART                   = 1
    SC_ACTION_REBOOT                    = 2
    SC_ACTION_RUN_COMMAND               = 3

    SERVICE_CONFIG_FAILURE_ACTIONS      = 2
)

type SERVICE_FAILURE_ACTIONS struct {
    ResetPeriod     uint32
    RebootMsg       *uint16
    Command         *uint16
    ActionsCount    uint32
    Actions         uintptr
}

type SC_ACTION struct {
    Type            uint32
    Delay           uint32
}

func setServiceFailureActions(handle windows.Handle) error {
    t := []SC_ACTION{
        { Type: SC_ACTION_RESTART, Delay: uint32(1000) },
        { Type: SC_ACTION_RESTART, Delay: uint32(10000) },
        { Type: SC_ACTION_RESTART, Delay: uint32(60000) },
    }
    m := SERVICE_FAILURE_ACTIONS{ ResetPeriod: uint32(60), ActionsCount: uint32(3), Actions: uintptr(unsafe.Pointer(&t[0])) }

    return windows.ChangeServiceConfig2(handle, SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&m)))
}

在我的基本示例中,您需要传递服务句柄,然后它将失败操作设置为硬编码的默认值:

  1. 1秒后第一次重新启动。
  2. 10秒后重新启动第二次。
  3. 第三次重新启动以及 60 秒后的任何后续次重新启动。
  4. 60 秒后重置失败计数器。

我刚刚测试过,似乎工作正常。


0
投票

golang.org/x/sys/windows/svc
实际上包含管理恢复操作的方法(它们可能是在编写原始接受的答案后添加的)。

请参阅以下

Service
方法:

  • SetRecoveryActions()
  • SetRecoveryActionsOnNonCrashFailures()
© www.soinside.com 2019 - 2024. All rights reserved.