在 Go 语言开发的程序部署到 Linux 服务器 这篇文章中提到了让应用程序在后台运行的方法,这篇文章讲的是如何将 Go 程序安装成系统服务(这篇文章中主要讲的 Windows 系统 和 Linux/(systemd) 系统)。
代码实现
最简单的方式是使用 github.com/kardianos/service 这个库,它支持 Windows XP+,Linux/(systemd | Upstart | SysV),和OSX/Launchd。使用示例如下:package main
import (
"log"
"github.com/kardianos/service"
)
var logger service.Logger
type program struct{}
func (p *program) Start(s service.Service) error {
// Start should not block. Do the actual work async.
go p.run()
return nil
}
func (p *program) run() {
// Do work here
}
func (p *program) Stop(s service.Service) error {
// Stop should not block. Return with a few seconds.
return nil
}
func main() {
svcConfig := &service.Config{
Name: "GoServiceExampleSimple",
DisplayName: "Go Service Example",
Description: "This is an example Go service.",
}
prg := &program{}
s, err := service.New(prg, svcConfig)
if err != nil {
logs.Error("创建服务失败,", err)
return
}
if len(os.Args) > 1 {
if os.Args[1] == "install" {
err := s.Install()
if err != nil {
logs.Error("服务安装失败,", err)
} else {
logs.Info("服务安装成功")
}
return
}
if os.Args[1] == "uninstall" {
err := s.Uninstall()
if err != nil {
logs.Error("服务卸载失败,", err)
} else {
logs.Info("服务卸载成功")
}
return
}
if os.Args[1] == "start" {
err := s.Start()
if err != nil {
logs.Error("启动服务失败,", err)
} else {
logs.Info("启动服务成功")
}
return
}
if os.Args[1] == "stop" {
err := s.Stop()
if err != nil {
logs.Error("停止服务失败,", err)
} else {
logs.Info("停止服务成功")
}
return
}
}
logs.Info("服务正在启动...")
err = s.Run()
if err != nil {
logs.Error("服务运行失败,", err)
return
}
logs.Info("服务正常停止")
}
如上面的代码,编译程序后可以在控制台使用 ./your-service 命令直接执行程序。如果想集成服务可以使用 ./your-service install 命令安装服务,使用 ./main uninstall 命令卸载服务,使用 ./your-service start 命令启动服务,使用 ./your-service stop 命令停止服务。
在 Windows 平台,可以运行 services.msc 查看服务启动及运行情况。
在 Linux 平台,执行 ./main install 命令安装服务后会生成一个 /etc/systemd/system/.service 文件(systemd )。可以使用 systemctl | grep your-service 查看服务是否已安装。
当然你也可以使用 service your-service start启动服务、使用 service your-service stop 停止服务、使用service your-service status命令查看服务运行状态及启动错误信息。如果想要开机启动,可以使用service your-service enable 命令。
Linux systemd 集成
我使用 systemd 来集成 Golang 程序作为一个系统服务的方法如下:
首先新建 systemd 的 service。假设程序放到 /usr/local/bin 目录,首先新建 service 文件,名称叫做 your-service:touch /etc/systemd/system/your-service.service
第二步,编辑该文件,输入的内容如下[Unit]
Description=服务描述
[Service]
Type=simple
Restart=always
RestartSec=5s
ExecStart=/usr/local/bin/your-service-dir/your-service
WorkingDirectory=/usr/local/bin/your-service-dir/
[Install]
WantedBy=multi-user.target
其中 ExecStart 是 Go 可执行文件的路径。WorkingDirectory 要注意,如果程序中使用了相对路径来加载一些配置文件,如果在 service 中没有配置 WorkingDirectory ,则默认是根路径,所以配置文件就从根路径来寻找,会造成一些意想不到的情况。当然你也可以在程序中使用如下代码指定运行目录:func main() {
// 更改程序目录 changed path for service
path, err := os.Executable()
if err != nil {
return
}
dir, err := filepath.Abs(filepath.Dir(path))
if err != nil {
return
}
err = os.Chdir(dir)
if err != nil {
return
}
// you code
}
最后就可以使用上面提到的命令 service your-service start启动服务、使用 service your-service stop 停止服务、使用service your-service status命令查看服务运行状态及启动错误信息。如果想要开机启动,可以使用service your-service enable 命令。