首页 > 解决方案 > exec.Command() 的 Golang cmd.Output() 在 systemd 服务(ubuntu)中引发错误

问题描述

cmd := exec.Command("xdpyinfo")我有一个 go 二进制文件,它使用then 调用获取显示信息cmd.Output()。该程序在终端中按预期运行。但是,当我将其作为 systemd 服务运行时,没有来自cmd.Output(). 我的程序作为服务运行,但调用 cmd.Output() 返回错误。

我试图让它尽可能容易重现:

我有一个名为 test 的可执行 go 二进制文件,/home/myusername/Projects/test 该二进制文件是使用包含以下代码go build的单个文件构建的:main.go

package main

import (
        "fmt"
        "log"
        "log/syslog"
        "os/exec"
)

func main() {
        logwriter, e := syslog.New(syslog.LOG_NOTICE, "testprog")
        if e == nil {
                log.SetOutput(logwriter)
        }

        cmd := exec.Command("xdpyinfo")

        out, err := cmd.Output()
        if err != nil {
                log.Print(fmt.Errorf("ERROR: %v", err))
        }

        log.Print(string(out))
}

日志记录仅用于测试目的,因为真实代码是更大应用程序的一部分。

当我在终端中运行测试二进制文件时,我会xdpyinfo在日志中看到预期的输出。但是,当尝试在服务中运行相同的二进制文件时,它会输出ERROR: exit status 1.

我运行该服务的步骤:

  1. 在以下位置创建一个单元服务文件/etc/systemd/system/TestProg.service
[Unit]
Description=Test service
ConditionPathExists=/home/myusername/Projects/test/test
After=network.target

[Service]
Type=simple

Restart=on-failure
RestartSec=10
startLimitIntervalSec=60

WorkingDirectory=/home/myusername/Projects/test
ExecStart=/home/myusername/Projects/test/test

[Install]
WantedBy=multi-user.target
  1. 启用服务:

sudo systemctl enable TestProg.service

  1. 启动服务:

sudo systemctl start TestProg.service

我还尝试将单元服务文件定位在/lib/systemd/system/TestProg.service并添加User=username下面的Type=simple.

我尝试了几种不同的配置来尝试使其正常工作。我还尝试使用SysProcAttr(使用实际的 uid 和 gid)设置用户:

cmd := exec.Command("xdpyinfo")

cmd.SysProcAttr = &syscall.SysProcAttr{
  Credential: &syscall.Credential{
    Uid:         uint32(uid),
    Gid:         uint32(gid),
    NoSetGroups: true,
  },
}

out, err := cmd.Output()
if err != nil {
        log.Print(fmt.Errorf("ERROR: %v", err))
}

我现在开始认为我错过了一些更基本的东西。

标签: ubuntugosystemd

解决方案


您必须在您的用户会话中运行它(这也启动了您的 X11 会话):

systemd-run --user -t  xdpyinfo |head
Running as unit: run-u1614.service
Press ^] three times within 1s to disconnect TTY.
name of display:    :0
version number:    11.0
vendor string:    The X.Org Foundation

你没有考试golang

sudo systemd-run -t  xdpyinfo 
Running as unit: run-u2876.service
Press ^] three times within 1s to disconnect TTY.
/usr/bin/xdpyinfo:  unable to open display "".

推荐阅读