bash - Go 应用程序作为 systemd 服务运行

标签 bash go operating-system systemd systemctl

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

在没有 Systemd 的情况下执行

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

在 golang 中,脚本执行代码被编写为当调用自动更新脚本时,它与 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 中运行脚本并取消拥有/分离它”的帖子已经发布,但找不到关于此类问题的任何帖子。如果我的理解有任何错误,请帮助我解决问题或纠正我。

最佳答案

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

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

It will run in a clean and detached execution environment.

关于bash - Go 应用程序作为 systemd 服务运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56953623/

相关文章:

bash - 如何使用多个变量构建路径

c++ - 调度程序是一个单独的进程还是仅在其他进程的上下文中运行

linux - 编译到内核中的驱动程序的 init 函数调用

multithreading - 条件变量与信号量

bash - docker neo4j 无法连接以从远程 url 加载 csv

bash - 使用长选项正确使用 bash getopts

golang x509.MarshalPKIXPublicKey 与 x509.MarshalPKCS1PublicKey()

go - 如何将主页和静态文件设置在同一路径

bash - 删除 HDFS 中在某个日期范围内创建的所有 0 字节文件

pointers - 在 Golang 中将类型 uintptr 分配给 uint64