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

Bash Go应用程序作为systemd服务运行,bash,go,operating-system,systemd,systemctl,Bash,Go,Operating System,Systemd,Systemctl,我们正在运行一个Golang应用程序,该应用程序在内部运行自动更新模块,以接收空中更新。在进行新更新时,autoupdate模块从s3下载新版本,并调用与可执行文件位于同一工作目录中的autoupdate bash脚本。autoupdate bash脚本执行的步骤将根据使用和不使用systemd处理的流程管理进行说明 无系统执行 通过PID杀死当前运行的golang应用程序 运行新下载的golang二进制文件 新版本公开了一个运行状况检查API,该API由脚本调用,以确保此版本是健康的 如果不正

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

无系统执行

  • 通过PID杀死当前运行的golang应用程序
  • 运行新下载的golang二进制文件
  • 新版本公开了一个运行状况检查API,该API由脚本调用,以确保此版本是健康的
  • 如果不正常,则执行回滚。新版本停止,旧版本启动
  • 在golang中,脚本执行代码是这样编写的:当调用autoupdate脚本时,它与golang应用程序的生命周期断开。i、 e bash脚本(子进程)即使在父进程(golang应用程序)被杀死后仍继续执行。从高尔夫球场跑步时效果良好

    问题:通过Systemd执行

    我们需要一个更干净的系统来处理启动、停止和故障重启功能。因此,我们决定将应用程序作为systemd服务运行。步骤与上面相同,但使用systemctl执行

  • 杀死当前运行的golang应用程序:“systemctl stop goapp.service”
  • 使用新的可执行路径更新systemd服务:“systemctl守护程序重新加载”
  • 重新启动systemd服务:“systemctl restart goapp.service”
  • 如果不正常,则执行回滚。新版本停止,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
    
    调用自动更新脚本的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中运行脚本并断开/分离脚本”的帖子已经发布,但找不到任何关于此类问题的帖子。如果我的理解有任何错误,请帮助我解决问题或纠正我

    调用与可执行文件位于同一工作目录中的autoupdate bash脚本

    我建议您使用。手册页摘录:

    它将在一段时间内运行 干净、独立的执行环境


    因此,您的问题只是“如何将其从systemd服务范围中分离?”@Flimzy是的,但我觉得详细说明这个问题很重要。systemd-run迫使我在脚本中使用绝对路径,我觉得这不是正确的继续方式。它似乎没有“-working dir”选项,比如systemctl被记录在手册页中,并且似乎不起作用,至少在我的情况下不起作用。您可以将当前工作目录路径作为参数提供给脚本,并在执行任何其他操作之前将其保存在cd中。Fabian感谢您提供的解决方案。systemd run确实解决了这个问题,但也有一些缺点。我目前正在研究如何将systemd run单元和systemctl服务的日志放在同一个单元下。@Achiles我不知道如何将两者联系起来。但另一个解决方案可能是让更新程序成为启动Golang应用程序的主导进程,如果Golang应用程序应该关闭,则向其发送中断信号。然后等待它关闭,更新二进制文件并再次启动它,所有这些都来自更新程序systemd单元。或者您可以尝试不让更新程序死掉?Fabian我能够使用以下命令将两者联系在一起:journalctl\u SYSTEMD\u UNIT=cantizconnect.service+SYSLOG\u IDENTIFIER=cantizconnect