在实际开发过程中,有时候会遇到如何编写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为我们提供了下面的参数使用,我们可以通过go build -o main main.go编译得到二进制文件,然后使用下面的命令来运行服务。

# 生成开机自启服务所需要的文件,文件位置根据操作系统的不同而不用,linux在 /etc/systemd/system 或者 /lib/systemd/system 下
./main install # 删除上面生成的文件
./main uninstall # 开启服务
./main start # 重启服务
./main restart # 停止服务
./main stop

2.2 kardianos/service 如何做开机自启服务

接下来以 Linux 为例,进行讲解。其他系统大家可自行尝试。

具体的步骤如下:

1、第一步是编写代码,编写完成后,编译成二进制文件。

代码就以 2.1 中的为例。首先编译成二进制文件。

go build -o main main.go

2、运行 可执行文件。

# 这将在 /etc/systemd/system 或者 /lib/systemd/system 中生成 custom-service.service 文件
# 我这里测试的时候是在 /etc/systemd/system 中生成的
./main install

看到这里,用过systemd的朋友应该可以猜到 kardianos/service 背后是通过什么来实现开机自启的。就是通过systemd来管理的。

3、将 custom-service.service 服务设置为开机自启.

运行下面命令将我们编写的程序设置为开机自启服务。

# 设置服务开机自启动
systemctl enable test-service.service
# 启动
systemctl start test-service.service

下面是systemctl常用的命令。

# 启动
systemctl start test-service.service # 停止
systemctl stop test-service.service # 设置服务开机自启动
systemctl enable test-service.service # 查询是否自启动服务
systemctl is-enabled test-service.service # 取消服务器开机自启动
systemctl disable test-service.service # 列出正在运行的服务
systemctl list-units --type=service

接下来我们看看服务管理器是什么意思?

1、./main install



2、查看custom-service.service文件

3、执行systemctl start custom-service.service后,查看服务运行过程

这里就是上面 服务管理器 的作用,也就是说,如何服务是手动运行的,那么 service.Interactive()返回 true,比如:./main start。如何是系统管理器运行的,则返回 false,比如:systemctl start custom-service.service。

2.3 结合 cli 使用

通过上面的例子,我们大概知道了如何使用 github.com/kardianos/service 。实际使用中,一般的服务都可以通过-h来查看帮助文档,但是我们我们通过./main -h会报错,所以需要完善下代码,使我们的程序更容易使用。下面,我们一起看看,借助 github.com/urfave/cli/v2 来完成上面的需求。

package main

import (
"fmt"
"github.com/kardianos/service"
"github.com/urfave/cli/v2"
"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() {
app := cli.NewApp()
app.Name = "custom-service"
app.Usage = "how to use custom service"
app.Commands = []*cli.Command{
{
Name: "install",
Action: ctrlAction,
},
{
Name: "uninstall",
Action: ctrlAction,
},
{
Name: "start",
Action: ctrlAction,
},
{
Name: "restart",
Action: ctrlAction,
},
{
Name: "stop",
Action: ctrlAction,
},
}
app.Flags = []cli.Flag{
&cli.StringFlag{
Name: "install",
Value: "install",
Usage: "Write the files required for startup",
},
&cli.StringFlag{
Name: "uninstall",
Value: "uninstall",
Usage: "Delete startup files",
},
&cli.StringFlag{
Name: "start",
Value: "start",
Usage: "start the service",
},
&cli.StringFlag{
Name: "stop",
Value: "stop",
Usage: "stop the service",
},
&cli.StringFlag{
Name: "restart",
Value: "restart",
Usage: "restart the service",
},
} app.Action = startAction app.Run(os.Args)
} func createSystemService() (service.Service, error) {
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 {
return nil, fmt.Errorf("service New failed, err: %v\n", err)
}
return s, nil
} func ctrlAction(c *cli.Context) error {
s, err := createSystemService()
if err != nil {
fmt.Printf("createSystemService failed, err: %v\n", err)
return err
}
err = service.Control(s, c.Command.Name)
if err != nil {
fmt.Printf("service Run 222 failed, err: %v\n", err)
return err
}
return nil
} func startAction(c *cli.Context) error {
s, err := createSystemService()
if err != nil {
fmt.Printf("createSystemService failed, err: %v\n", err)
return err
}
// 默认 运行 Run
err = s.Run()
if err != nil {
fmt.Printf("service Run failed, err: %v\n", err)
return err
} return nil
}

大家可以根据自己的需求进行开发,这里只是讲一个简单的案例而已。

编译:

go build -o main main.go

运行:

./main -h

NAME:
custom-service - how to use custom service USAGE:
custom-service [global options] command [command options] [arguments...] COMMANDS:
install
uninstall
start
restart
stop
help, h Shows a list of commands or help for one command GLOBAL OPTIONS:
--install value Write the files required for startup (default: "install")
--uninstall value Delete startup files (default: "uninstall")
--start value start the service (default: "start")
--stop value stop the service (default: "stop")
--restart value restart the service (default: "restart")
--help, -h show help

浅谈如何使用 github.com/kardianos/service的更多相关文章

  1. 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6627260 在前面一篇文章浅谈Service ...

  2. Web Service进阶(七)浅谈SOAP Webservice和RESTful Webservice

    浅谈SOAP Webservice和RESTful Webservice REST是一种架构风格,其核心是面向资源,REST专门针对网络应用设计和开发方式,以降低开发的复杂性,提高系统的可伸缩性.RE ...

  3. 浅谈 kubernetes service 那些事(上篇)

    一.问题 首先,我们思考这样一个问题: 访问k8s集群中的pod, 客户端需要知道pod地址,需要感知pod的状态.那如何获取各个pod的地址?若某一node上的pod故障,客户端如何感知? 二.k8 ...

  4. 浅谈 kubernetes service 那些事 (下篇)

    欢迎访问网易云社区,了解更多网易技术产品运营经验. 五.K8s 1.8 新特性--ipvs ipvs与iptables的性能差异 随着服务的数量增长,IPTables 规则则会成倍增长,这样带来的问题 ...

  5. Service Cloud 零基础(一)Case 浅谈

    本片参考:https://resources.docs.salesforce.com/222/latest/en-us/sfdc/pdf/salesforce_case_implementation_ ...

  6. 浅谈服务治理、微服务与Service Mesh(三) Service Mesh与Serverless

    作为本系列文章的第三篇(前两篇<浅谈服务治理.微服务与Service Mesh(一)Dubbo的前世今生>,<浅谈服务治理.微服务与Service Mesh(二) Spring Cl ...

  7. 浅谈angular2+ionic2

    浅谈angular2+ionic2   前言: 不要用angular的语法去写angular2,有人说二者就像Java和JavaScript的区别.   1. 项目所用:angular2+ionic2 ...

  8. 浅谈HTML5单页面架构(一)——requirejs + angular + angular-route

    心血来潮,打算结合实际开发的经验,浅谈一下HTML5单页面App或网页的架构. 众所周知,现在移动Webapp越来越多,例如天猫.京东.国美这些都是很好的例子.而在Webapp中,又要数单页面架构体验 ...

  9. [UWP]浅谈按钮设计

    一时兴起想谈谈UWP按钮的设计. 按钮是UI中最重要的元素之一,可能也是用得最多的交互元素.好的按钮设计可以有效提高用户体验,构造让人眼前一亮的UI.而且按钮通常不会影响布局,小小的按钮无论怎么改也不 ...

  10. URL跳转与webview安全浅谈

    URL跳转与webview安全浅谈 我博客的两篇文章拼接在一起所以可能看起来有些乱 起因 在一次测试中我用burpsuite搜索了关键词url找到了某处url我测试了一下发现waf拦截了指向外域的请求 ...

随机推荐

  1. Apache + PHP + Mysql Windows下配置

    1.安装Apache 下载网址 http://httpd.apache.org/download.cgi#apache24 二.下载php 下载地址:https://www.php.net/downl ...

  2. 按正斜线输出M*N的矩阵

    public static void outMatrix(int[][] array) { for(int row=0;row<array.length;row++) { int scolumn ...

  3. 中文数据导入到hive,出现乱码

    中文数据导入到hive,出现乱码 解决方法: 右键要导入的数据文件,选择用Notepad++打开,然后点击"编辑"-->转为UTF-8,最后保存即可. 然后在上传到指定路径下 ...

  4. python数据结构转字符串_python2中字符不显示问题_python2_递归

    # encoding:utf-8 def get_str(data): """将python数据转化为肉眼可见的字符串 :param data: str.dict.lis ...

  5. 容灾恢复 | 记一次K8S集群中etcd数据快照的备份恢复实践

    [点击 关注「 全栈工程师修炼指南」公众号 ] 设为「️ 星标」带你从基础入门 到 全栈实践 再到 放弃学习! 涉及 网络安全运维.应用开发.物联网IOT.学习路径 .个人感悟 等知识分享. 希望各位 ...

  6. 痞子衡嵌入式:在i.MXRT1060-EVK上利用memtester程序给SDRAM做压力测试

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是在i.MXRT1060-EVK上利用memtester程序给SDRAM做压力测试. 我们知道恩智浦i.MXRT1xxx系列是高性能MCU ...

  7. 在CentOS中安装Docker

    概述 Docker是一款使用Golang开发的开源容器引擎,我们可以使用Docker将自己的应用和相关依赖进行打包,实现在不同服务器上进行快速部署,而不需要再更多关注部署环境的差异性.结合kubern ...

  8. 新版TinyCore Linux系统安装

    1.设置软件仓库源echo "https://mirrors.163.com/tinycorelinux">/opt/tcemirror 2.安装启动加载器及其依赖tce-l ...

  9. js函数防抖节流

    // 3.1 函数防抖: // 当持续触发事件时,一定时间段内没有再次触发事件,事件处理函数才会执行一次,如果设定时间到来之前,又触发了事件,就重新开始延时.// 也就是说当一个用户一直触发这个函数, ...

  10. node-sass与node版本对照图