使应用程序作为系统服务运行

时间:2019-07-09 13:22:26

标签: bash go operating-system systemd systemctl

我们正在运行一个Golang应用程序,该应用程序内部运行一个自动更新模块以接收空中更新。在进行新更新时,自动更新模块从s3下载新版本,并调用与可执行文件相同的工作目录中存在的自动更新bash脚本。自动更新bash脚本执行的步骤将根据使用和不使用systemd处理的流程管理进行说明。

不带系统的执行

  1. 通过PID杀死当前正在运行的golang应用程序
  2. 运行新下载的golang二进制文件。
  3. 新版本公开了运行状况检查API,脚本会调用该运行状况检查API以确保此版本运行状况良好。
  4. 如果不健康,将执行回滚。新版本已停止,旧版本已启动。

在golang中,脚本执行代码被编写为使得在调用autoupdate脚本时,它会脱离golang应用程序的生命周期。即bash脚本(子进程)即使在父进程(golang应用程序)被杀死后仍继续执行。从GoLand IDE运行时,效果很好。

问题:通过Systemd执行

我们需要一个更清洁的系统来处理启动,停止,重新启动失败功能。因此我们决定将应用程序作为systemd服务运行。步骤与上述相同,但使用systemctl

执行
  1. 杀死当前正在运行的golang应用程序:“ systemctl stop goapp.service”
  2. 使用新的可执行路径更新systemd服务:“ systemctl daemon-reload”
  3. 重新启动systemd服务:“ systemctl restart goapp.service”
  4. 如果不健康,将执行回滚。停止新版本,使用旧版本更新systemd服务文件,并启动旧版本。

在通过systemd执行应用程序时,一旦在上述步骤1中使用命令“ sudo systemctl stop goapp.service”停止systemctl服务,脚本就会立即退出。这意味着golang应用执行的脚本的生命周期显然与systemd服务的生命周期相关。如何将其与systemd服务范围分开?

系统服务文件

[Unit]
Description=Goapp
After=docker.service
Requires=docker.service
Requires=docker-mysql.service
Requires=docker-redis.service
StartLimitInterval=200
StartLimitBurst=5

[Service]
User=root
Environment=AWS_SHARED_CREDENTIALS_FILE=/home/username/.aws/credentials
Restart=on-failure
RestartSec=30
WorkingDirectory=/home/username/go/src/goapp-v2.0.0
ExecStart=/home/username/go/src/goapp-v2.0.0/goexecutable --autoupdate=true

[Install]
WantedBy=multi-user.target

调用自动更新bashscript的Golang代码部分

func scriptExecutor(argsliceString []string, remoteVersion *semver.Version, localVersion *semver.Version) {

newVersion := fmt.Sprint(remoteVersion)
previousVersion := fmt.Sprint(localVersion)
argslice := append(argsliceString, newVersion, previousVersion)
scriptParams := append([]string{"./autoupdate-script.sh"}, argslice...)
Info("Autoupdater - New version ", newVersion)
Info("Autoupdater - Existing Version ", previousVersion)
Info("Autoupdater - Executing shell script to upgrade go app.Passing parameters ", scriptParams) // ./autoupdate-script.sh goexecutable 7.1.0 7.0.0
cmd := exec.Command("sudo", scriptParams...)
err := cmd.Start()
if err!=nil{
    Info(err)
}
cmd.Process.Release()

}

有关“如何在Golang中运行脚本以及如何取消/分离脚本”的帖子已发布,但找不到有关此类问题的任何帖子。如果我的理解有任何错误,请帮助我解决问题或纠正我。

1 个答案:

答案 0 :(得分:1)

  

在与可执行文件相同的工作目录中调用自动更新bash脚本。

我建议使用systemd-run运行它。摘录于手册页:

  

它将在          干净且独立的执行环境。