DengQN·一个普通程序员;
【Crudboy日常】 windows服务注册工具
2024-03-08 18:19 660

起因

之前使用了 winsw/winsw 来注册程序到windows服务

后来某项目使用了windows server 2008, 刚好因为winsw

WinSW 3 can run on Windows platforms with .NET Framework 4.6.1
or later versions installed. For systems without .NET Framework, the project provides native 64-bit and 32-bit executables based on .NET 7.

直接报错。
QQ截图20240308182259.png

替代

找到项目 kardianos/service, 是基于golang开发的,结构简单,适合二次开发。

实现

程序需要实现接口

type Interface interface {
	// Start provides a place to initiate the service. The service doesn't
	// signal a completed start until after this function returns, so the
	// Start function must not take more then a few seconds at most.
	Start(s Service) error

	// Stop provides a place to clean up program execution before it is terminated.
	// It should not take more then a few seconds to execute.
	// Stop should not call os.Exit directly in the function.
	Stop(s Service) error
}

要注意的是需要在Start接口内异步操作业务,直接go关键字跑一下就好了。

然后就可以新建配置并创建服务

svcConfig := &service.Config{
    Name:        config.Name,
    DisplayName: config.Name,
    Description: config.Description,
}

s, err := service.New(prg, svcConfig)
if err != nil {
    log.Fatal(err)
}

prg是接口Interface的实现

其中service.Config的参数有很多, 比如Executable等。 其中我们需要通过读取配置文件的方式来获取到程序需要的参数。

比如:Start函数响应时要执行的命令和参数、日志的路径、服务注册时需要的名称、描述等。

最后判断下参数,看是传递service还是直接跑就行了

if len(*svcFlag) != 0 {
    log.Println("scvFlag: ", *svcFlag)
    err := service.Control(s, *svcFlag)
    if err != nil {
        log.Printf("Valid actions: %q\n", service.ControlAction)
        log.Fatal(err)
    }
    return
}
err = s.Run()
if err != nil {
    logger.Error(err)
}

  • 1、工作路径

注册到服务后,工作路径是系统目录,需要程序切换到正确的工作路径。

先是找到程序本身的位置

fullexecpath, err := os.Executable()
if err != nil {
    panic(err.Error())
}

dir, _ := filepath.Split(fullexecpath)
os.Chdir(dir)