为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
月关宝盒 2021-12-07 17:18:23
我正在使用该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 以编程方式配置这些选项的功能。我已经做了一些挖掘,看起来它们是通过将结构传递给ChangeServiceConfig2in来配置的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 构建和传递该结构 - 有没有人有任何见解?
查看完整描述

1 回答

?
眼眸繁星

TA贡献1873条经验 获得超9个赞

经过这里的一些指导,加上阅读现有 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 秒后重置故障计数器。

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


查看完整回答
反对 回复 2021-12-07
  • 1 回答
  • 0 关注
  • 322 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信