如何配置用Go编写的Windows服务的失败操作? [英] How do I configure failure actions of a Windows service written in Go?
问题描述
我使用 golang.org/x/sys/windows/svc
软件包在Go中编写Windows服务。
到目前为止,这一切都很好,很容易开始,我很喜欢它。
我写了一些自动更新功能,我我希望服务在完成更新时自动重启。
我试过产生一个进程,使用重新启动服务, SCM
,但它记录了一条错误消息,这似乎是在尝试以本地系统身份运行时控制服务。
服务进程无法连接到服务控制器。
更好/更简单的方法似乎是 os.Exit(1)
并将服务失败操作
设置为重新启动失败
,这非常出色! / p>
唯一的问题是,似乎没有使用Go以编程方式配置这些选项的功能。
我已经做了一些挖掘,看起来他们是通过在 advapi32.dll
中将结构传递给 ChangeServiceConfig2
- 如何创建在崩溃时重新启动的服务
$ b
在 golang / sys / blob / master / windows / svc / mgr / config.go - func updateDescription(句柄窗口。代码已经调用了
windows.ChangeServiceConfig2
,它是一个指向DLL调用的链接。
Microsoft文档用于 SERVIC E_FAILURE_ACTIONS
结构为此处。
我很难弄清楚如何使用Go构建和传递结构 - 有没有人有任何见解?
在 ),再加上通过现有Go Windows服务接口的源代码阅读,我想出了自己的答案,我将在下面进行介绍。 / p>
对于使用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
)
类型SERVICE_FAILURE_ACTIONS结构{
ResetPeriod uint32
RebootMsg * uint16
命令* uint16
ActionsCount uint32
操作uintptr
}
类型SC_ACTION结构{
类型uint32
延迟uint32
}
func setServiceFailureActions(句柄windows.Handle)错误{
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),操作:uintptr (unsafe.Pointer(& t [0]))}
return windows.ChangeServiceConfig2(handle,SERVICE_CONFIG_FAILURE_ACTIONS,(* byte)(unsafe.Pointer(& m)))
}
在我的基本示例中,您需要传递一个服务句柄,然后它将设置失败操作到硬编码默认值:
- 1秒后首次重新启动。
- 重新启动
- 在第60秒后重新开始第三次以及任何后续时间。
- 在60秒后重置故障计数器。
/ li>
- 重新启动
我刚刚测试过,它似乎可以正常工作。
I'm writing a Windows Service in Go using the golang.org/x/sys/windows/svc
package.
So far, it's all working great and so easy to get started with, I love it.
I've written in some auto update functionality and I'm wanting the service to restart itself when it has completed an update.
I've tried spawning a process that will restart the service using the SCM
, but it logs an error message which seems to be to do with trying to control the service while running as Local System.
The service process could not connect to the service controller.
A better/easier way seems to be to os.Exit(1)
and have the service Failure Actions
set to Restart on Failure
, which works brilliantly!
The only trouble is, there doesn't seem to be the functionality to configure those options programatically using Go.
I've done some digging and it looks like they are configured by passing a struct to ChangeServiceConfig2
in advapi32.dll
- How to create service which restarts on crash
In golang/sys/blob/master/windows/svc/mgr/config.go - func updateDescription(handle windows.Handle, desc string) error
The code already calls windows.ChangeServiceConfig2
which is a link to the DLL call.
And the Microsoft docs for the SERVICE_FAILURE_ACTIONS
struct are here.
I'm having trouble figuring out how to build and pass that struct using Go - does anyone have any insights?
After some guidance from here, plus reading through the source code for the existing Go Windows Service interface, I came up with my own answer, which I'll try to document below.
For type reference when working with the Windows DLLs, the MSDN docs are here.
My code looks like this:
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)))
}
In my basic example, you need to pass a Service Handle, then it'll set the failure actions to a hard coded default of:
- Restart the first time after 1 second.
- Restart the second time after 10 seconds.
- Restart the third time and any subsequent times after 60 seconds.
- Reset the failure counter after 60 seconds.
I've just tested and it seems to work ok.
这篇关于如何配置用Go编写的Windows服务的失败操作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!