Systemd 未检测到 GOPATH(运行 没有二进制文件)

Systemd doesn't detect GOPATH (run without binary file)

我写了简单的 systemd 服务文件 goserver.service:

[Unit]
Description=Goserver

[Service]
ExecStart=/usr/bin/go run /home/denis/goserver/index.go

[Install]
WantedBy=multi-user.target

但是当我尝试 运行 服务并获取状态时:

$ sudo systemctl status goserver.service

我收到错误:

мар 02 12:28:04 DV go[13627]: home/denis/goserver/index.go:6:2: cannot find package "gopkg.in/mgo.v2" in any of:
мар 02 12:28:04 DV go[13627]:         /usr/lib/go-1.6/src/gopkg.in/mgo.v2 (from $GOROOT)
мар 02 12:28:04 DV go[13627]:         ($GOPATH not set)

但是 $GOPATH 是用 export 命令设置的:

$ export GOPATH="/home/denis/goserver/"

$ ls $GOPATH
goserver.log  index.go  pkg  src  templates

来自命令行的这条命令工作正常:

$ /usr/bin/go run /home/denis/goserver/index.go

但如果我使用 systemd 服务,它就不起作用。

如何 运行 systemd 服务检测到 $GOPATH? (没有由命令 go build... 创建的二进制文件)

您创建的服务很可能 运行 与不同的用户(很可能 root 是默认值),其中可能没有 GOPATH 环境变量集(或可能指向不同的文件夹)。

您不应该使用 go run 到 运行 用 go 编写的服务。首先使用 go buildgo install(更多信息:)将它们编译为可执行二进制文件,然后在 ExecStart 中启动可执行二进制文件。这样你就不会依赖 GOPATH 之类的东西和正在安装的依赖项(因为 building/installing 只有在它们存在的情况下才会成功)。

如果您真的想使用 go run,请确保为启动服务的用户设置了 GOPATH;并且用户对 GOPATH 文件夹具有适当的权限(因为它位于用户主文件夹中)。另请注意,您可以在 [Service] 部分中指定 User=Group= 指令,因此您可以控制启动服务的用户。

具有干净环境的 systemd 服务 运行,因此它不会被用户在启动服务时恰好处于的任何随机环境所破坏。

所以你需要在你的服务文件中设置GOPATH

[Service]
Environment=GOPATH=/home/denis/goserver/
ExecStart=/usr/bin/go run /home/denis/goserver/index.go

虽然这是一个非常不寻常的设置,您通常在其他地方构建您的应用程序,并将服务指向现有的二进制文件,并且没有编译服务并且 运行 您的代码具有所有潜力可能带来的问题(当前代码无法编译,服务器意外暴露其源代码的可能性增加等)