golang 应用程序的服务文件

golang 应用程序的服务文件

因此我编写了一个 golang 应用程序,我希望systemd每次服务器重启时都初始化它。

这是服务文件:-

[Unit]
Description=golang wiki initialization

[Service]
Type=forking
PIDFile=/tmp/gowiki.pid-3030
User=root
Group=root
WorkingDirectory=/var/www
ExecStart=/bin/bash -c 'daemonize -o stdout.log -e stderr.log /var/www/wiki'

[Install]
WantedBy=multi-user.target

每当我重新启动服务器时,它似乎都能正常工作,但是当我gowiki在终端中手动启动或重新启动时,仍然会遇到稍微令人恼火的问题:-

systemctl start gowiki

或者

systemctl restart gowiki

这确实使我的 gowiki 进程运行;但是,执行命令后systemctl start gowiki,我的终端被冻结,并且命令似乎没有退出,直到我手动强制按 Ctrl-C。

我做错了什么导致了这个问题?

答案1

这有效。

[Unit]
Description=golang wiki initialization

[Service]
PIDFile=/tmp/gowiki.pid-4040
User=root
Group=root
WorkingDirectory=/var/www
ExecStart=/bin/bash -c '/var/www/wiki'

[Install]
WantedBy=multi-user.target

因为Type=forking服务期望父服务在实际启动之前退出。如果父服务从未退出,则 systemctl start 将不会返回提示,因为它认为它尚未完成执行。

答案2

如果您不介意针对 systemd 稍微调整一下代码,那么迄今为止我发现的最干净的解决方案是使用 SDNotify 信号。

import "github.com/coreos/go-systemd/daemon"

func main() {
    // Important init stuff here
    ....

    // Notify systemd that we're ready
    sent, e := daemon.SdNotify(false, "READY=1")
    if e != nil {
        log.Fatal(e)
    }
    if !sent {
        log.Printf("SystemD notify NOT sent\n")
    }

    // And do something blocking like listening for HTTP(s)
  • 它没有 CGO-deps
  • 该代码也可在非 systemd 系统上运行(在这种情况下,它会发出警告“通知未发送”)
  • 如果你想要一个可以工作的例子:https://github.com/mpdroog/dnsleak

您对应的 systemd 单元文件:

[Unit]
Description=golang wiki initialization
After=network.target
Requires=network.target

[Service]
Type=notify

Restart=always
RestartSec=30
TimeoutStartSec=0

WorkingDirectory=/var/www
ExecStart=/var/www/wiki
User=www-data
Group=www-data
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target

相关内容