将应用程序 运行 转为 systemd 服务

Go application run as systemd service

我们正在 运行 构建一个内部 运行 自动更新模块以接收无线更新的 Golang 应用程序。在新更新时,自动更新模块从 s3 下载新版本并调用与可执行文件位于同一工作目录中的自动更新 bash 脚本。 autoupdate bash 脚本执行的步骤在使用和不使用 systemd 处理的进程管理方面进行了解释。

不使用 Systemd 执行

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

在 golang 中,脚本执行代码被编写为当调用自动更新脚本时,它与 golang 应用程序的生命周期无关。即 bash 脚本(子进程)即使在父进程(golang 应用程序)被杀死后仍继续执行。当从 GoLand 运行ning IDE.

时它工作正常

问题:通过 Systemd 执行

我们需要一个更干净的系统来处理启动、停止、重启失败功能。所以我们决定 运行 应用程序作为 systemd service.The 步骤与上面相同,但使用 systemctl

执行
  1. 杀死当前 运行ning 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 服务的范围中分离出来?

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

调用自动更新的Golang代码部分bash脚本

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()

}

"how to run a script in Golang and disown/detach it" 上的帖子已发布,但找不到关于此类问题的任何帖子。如果我的理解有任何错误,请帮助我解决问题或纠正我。

invokes an autoupdate bash script present in the same working directory as the executable.

我会推荐 运行 它和 systemd-run。摘自man-page:

It will run in a clean and detached execution environment.