У меня есть двоичный файл go, который получает отображаемую информацию, используя cmd := exec.Command("xdpyinfo")
, а затем вызывает cmd.Output()
. Программа работает в терминале как положено. Однако, когда я запускаю это как службу systemd, из cmd.Output()
не выводится. У меня программа работает как служба, но вызов cmd.Output () возвращает ошибку.
Я попытался максимально упростить воспроизведение:
У меня есть исполняемый файл 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
.
Шаги, которые я предпринял для запуска службы:
- Создайте файл службы модуля в
/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
Включить услугу:
sudo systemctl enable TestProg.service
Запустить службу:
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))
}
Теперь я начинаю думать, что мне не хватает чего-то более фундаментального.