在实际开发过程中,有时候会遇到如何编写Go开机自启服务的需求,在linux中我们可以使用systemd
来进行托管,windows下可以通过注册表
来实现,mac下可以通过launchd
来实现,上面的方式对于开发者来说,并不是什么困难的事情,但是对于使用者而言,是并不希望通过这么复杂的方式来达到开机自启的功能的。这个时候,作为开发者,就需要使用其他的方式来实现开机自启的功能,下面讲一个Go中,借助这个库 github.com/kardianos/service 来简化如何实现开机自启功能。
1、github.com/kardianos/service 基础介绍
1.1 kardianos/service 简介
我们先来看一看 github.com/kardianos/service 上面的自我介绍:Run go programs as a service on major platforms.
如何理解上面这句话呢,上面这句话翻译出来的意思是:"在主要平台上将Go程序作为服务运行"。
这意味着我们可以将Go编写的程序以服务的形式在主要操作系统上运行,例如Windows、Linux、macOS等。这意味着程序可以在后台持续运行,而不需要用户手动启动或停止它们。这种方式可以提高程序的可靠性和稳定性,同时也方便了程序的管理和监控。
那该如何理解服务
呢?
服务(Service)是指在计算机系统中,为用户或其他程序提供某种功能的程序或进程。服务通常在后台运行,可以长时间运行,不需要用户交互,可以自动启动和停止。服务可以提供各种功能,如网络服务、数据库服务、文件共享服务等。在操作系统中,服务通常以服务进程的形式运行,可以通过系统管理工具进行管理和配置。
有了上面的了解过后,再来看看官方自己的描述。service will install / un-install, start / stop, and run a program as a service (daemon). Currently supports Windows XP+, Linux/(systemd | Upstart | SysV), and OSX/Launchd.
如何理解上面这句话呢,我说说自己的理解。
我们可以将编写好的代码打包成二进制文件后,通过
二进制文件名 + install / un-install, start / stop
来运行我们的服务,程序将作为服务(守护进程)运行。目前支持Windows XP+、Linux/(systemd|Upstart|SysV)和OSX/Launchd。
Windows controls services by setting up callbacks that is non-trivial. This is very different then other systems. This package provides the same API despite the substantial differences. It also can be used to detect how a program is called, from an interactive terminal or from a service manager.
下面是我的理解:
Windows 通过设置回调来控制服务,这与其他系统非常不同。这个包提供了相同的API,尽管存在很大差异。它还可以用于检测程序是从交互式终端还是从服务管理器调用的。
看到这里的时候,我其他不太理解最后一句话,什么叫从
服务管理器
调用。将在 2.2 章节中介绍。
1.2 kardianos/service 安装
安装 github.com/kardianos/service 的方式和其他方式一样。
go get github.com/kardianos/service
指定版本方式
go get github.com/kardianos/service@v1.2.2
2、kardianos/service 使用方式
以下介绍都是基于 github.com/kardianos/service@v1.2.2 进行讲解的。
2.1 kardianos/service 简单的使用
我们先来看一个简单的例子,代码如下:
package main
import (
"fmt"
"github.com/kardianos/service"
"os"
)
type SystemService struct {}
func (ss *SystemService) Start(s service.Service) error {
fmt.Println("coming Start.......")
go ss.run()
return nil
}
func (ss *SystemService) run() {
fmt.Println("coming run.......")
}
func (ss *SystemService) Stop(s service.Service) error {
fmt.Println("coming Stop.......")
return nil
}
func main() {
fmt.Println("service.Interactive()---->", service.Interactive())
svcConfig := &service.Config{
Name: "custom-service",
DisplayName: "custom service",
Description: "this is github.com/kardianos/service test case",
}
ss := &SystemService{}
s, err := service.New(ss, svcConfig)
if err != nil {
fmt.Printf("service New failed, err: %v\n", err)
os.Exit(1)
}
if len(os.Args) > 1 {
err = service.Control(s, os.Args[1])
if err != nil {
fmt.Printf("service Control 111 failed, err: %v\n", err)
os.Exit(1)
}
return
}
// 默认 运行 Run
err = s.Run()
if err != nil {
fmt.Printf("service Control 222 failed, err: %v\n", err)
os.Exit(1)
}
}
通过go run main.go
得到如下结果,注意:程序并不会终止,而是阻塞住了
。
service.Interactive()----> true
coming Start.......
coming run.......
实际上,kardianos/service
为我们提供了下面的参数