如何配置用 Go 编写的 Windows 服务的失败操作?
How do I configure failure actions of a Windows service written in Go?
我正在使用 golang.org/x/sys/windows/svc
包在 Go 中编写一个 Windows 服务。
到目前为止,一切都很好,而且很容易上手,我喜欢它。
我已经编写了一些自动更新功能,我希望该服务在完成更新后自行重启。
我已经尝试生成一个将使用 SCM
重新启动服务的进程,但它记录了一条错误消息,这似乎与在 运行 时尝试控制服务有关本地系统。
The service process could not connect to the service controller.
better/easier 方法似乎是 os.Exit(1)
并将服务 Failure Actions
设置为 Restart on Failure
,效果非常好!
唯一的问题是,似乎没有使用 Go 以编程方式配置这些选项的功能。
我做了一些挖掘,看起来它们是通过将结构传递给 advapi32.dll
中的 ChangeServiceConfig2
- How to create service which restarts on crash
来配置的
在golang/sys/blob/master/windows/svc/mgr/config.go - func updateDescription(handle windows.Handle, desc string) error
代码已经调用了 windows.ChangeServiceConfig2
,这是对 DLL 调用的 link。
SERVICE_FAILURE_ACTIONS
结构的 Microsoft 文档是 here。
我无法弄清楚如何使用 Go 构建和传递该结构 - 有人有任何见解吗?
在 here 的一些指导以及通读现有 Go Windows 服务接口的源代码后,我得出了自己的答案,我将在下面记录下来。
对于使用 Windows DLL 时的类型参考,MSDN 文档是 here。
我的代码如下所示:
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秒后第一次重启
- 10 秒后重新启动第二次。
- 第三次和 60 秒后的任何后续时间重新启动。
- 60 秒后重置失败计数器。
我刚刚测试过,似乎工作正常。
我正在使用 golang.org/x/sys/windows/svc
包在 Go 中编写一个 Windows 服务。
到目前为止,一切都很好,而且很容易上手,我喜欢它。
我已经编写了一些自动更新功能,我希望该服务在完成更新后自行重启。
我已经尝试生成一个将使用 SCM
重新启动服务的进程,但它记录了一条错误消息,这似乎与在 运行 时尝试控制服务有关本地系统。
The service process could not connect to the service controller.
better/easier 方法似乎是 os.Exit(1)
并将服务 Failure Actions
设置为 Restart on Failure
,效果非常好!
唯一的问题是,似乎没有使用 Go 以编程方式配置这些选项的功能。
我做了一些挖掘,看起来它们是通过将结构传递给 advapi32.dll
中的 ChangeServiceConfig2
- How to create service which restarts on crash
在golang/sys/blob/master/windows/svc/mgr/config.go - func updateDescription(handle windows.Handle, desc string) error
代码已经调用了 windows.ChangeServiceConfig2
,这是对 DLL 调用的 link。
SERVICE_FAILURE_ACTIONS
结构的 Microsoft 文档是 here。
我无法弄清楚如何使用 Go 构建和传递该结构 - 有人有任何见解吗?
在 here 的一些指导以及通读现有 Go Windows 服务接口的源代码后,我得出了自己的答案,我将在下面记录下来。
对于使用 Windows DLL 时的类型参考,MSDN 文档是 here。
我的代码如下所示:
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秒后第一次重启
- 10 秒后重新启动第二次。
- 第三次和 60 秒后的任何后续时间重新启动。
- 60 秒后重置失败计数器。
我刚刚测试过,似乎工作正常。