systemd 显然找不到 .service 文件

60
我已经为我们的foo服务编写了一个foo.service文件,它作为守护进程运行。当我运行systemctl start foo(和stop)时,服务可以正常运行,但systemctl enable foo的结果是Failed to issue method call: Invalid argument。单元文件放置在/etc/systemd/system/foo.service中,并具有0755的权限。将systemd设置为调试模式并运行enable命令会得到:
Looking for unit files in (highest priority first):`
    /etc/systemd/system
    /run/systemd/system
    /usr/local/lib/systemd/system
    /usr/lib/systemd/system
Looking for SysV init scripts in:
    /etc/rc.d/init.d
Looking for SysV rcN.d links in:
    /etc/rd.c
Failed to issue method call: Invalid argument

在进行谷歌搜索后,似乎systemctl找不到.service文件。有没有办法可以验证?如果可以,我该如何解决?是否有其他可能出错的想法?是否可以启用更多调试信息帮助我缩小问题范围?给出的调试信息并没有真正帮助我确定问题。

foo.service 的内容如下:

[Unit]
Description=Blah Blah Blah

[Service]
ExecStart=/usr/bar/doof/foo
Type=simple
PIDFile=/var/run/foo.pid

[Install]
WantedBy=multi-user.target,graphical.target

编辑:是的,我确实运行了systemctl daemon-reload命令。


3
在添加或更改foo.service文件后,您是否运行了systemctl daemon-reload命令? - nos
是的,我已经运行了 daemon-reload。 - user3255510
8个回答

102

针对来自Google的人:

  • 使用sudo systemd-analyze verify NAME.service进行验证
  • 当使用符号链接时,请确保它使用绝对路径
  • 确保名称为/etc/systemd/system/*.service
  • 更改后执行sudo systemctl daemon-reload

6
对我而言,我一开始执行的是软链接 (ln -s ... ...)。后来我尝试了硬链接 (ln ... ...),并且它也成功了。 - Anand Undavia
2
@AnandUndavia 当你使用硬链接时,应该会收到一个错误:*.service不是符号链接,忽略。 - Jonathan Komar
sudo systemd-analyze verify xxx gave me Unknown operation 'verify' - Pierre de LESPINAY
@PierredeLESPINAY 在v248版本中仍然在手册中,但如果您找到原因/解决方法,请将其编辑到答案中! - Mark
当我查找foo守护进程时,出现了“Unit foo.service not found”的错误,即使我指定了绝对路径,难道它被systemctl用另一个名称识别了吗? - jimmymcheung

28
在我的情况下,问题在于文件是从另一个分区进行符号链接,而systemd 不支持这样做。

单元文件必须驻留在在主 PID 1 被调用的时刻挂载的分区上。即根分区或一些由 initrd 预先装载的其他分区。

我在回答一个旧问题,因为这是搜索此问题时的顶级结果,可能会对某些人有所帮助。


谢谢。最糟糕的是,从来没有打印出与此有关的错误! - undefined

25

我在谷歌上搜索"systemctl unit not found"时发现了这个问题。

在我的情况下,我通过podman生成了一个*.service文件,但无论我做了什么,systemctl都找不到该服务文件。

解决方法是检查selinux并设置正确的标签。例如:

/sbin/restorecon -v /etc/systemd/system/container_httpd.service

2
谢谢!这对我有用。你能详细说明它具体是做什么的吗? - Niwla23
好解决方案,确实podman generate有问题。 - TecHunter
@Niwla23 Selinux限制systemd只能查看标记为systemd_unit_file_t的文件。所讨论的服务文件是在其他地方创建的(通常由podman-generate生成),然后移动到这里。由于移动文件不会更新其标签,因此该文件保留了它创建时分配的原始(不同)标签,因此无法被systemd看到。restorecon根据/etc/selinux/targeted/contexts/files中的持久规则重置文件上下文,从而“修正”了标签。 - cyqsimon

7

确保如果您将单元放在用户文件夹.config/systemd/user/*.service中,则需要以以下方式运行命令:

systemd --user <command>

(请注意 --user 参数)


3

出错是因为在WantedBy指定了两个目标。只需这样说明即可:

[Install]
WantedBy=multi-user.target

我真的不知道我们如何指定两个目标。

5
多个目标之间用空格分隔,而不是逗号分隔。 - James M. Lay
WantedBy选项可以使用多次,或者可以给出一个以空格分隔的单元名称列表。因此,这个答案是正确的。 - Pramod

2

之前在添加自己的单元时遇到了这个问题,结果发现SELinux的上下文错误或缺失。如果在强制执行模式下进行测试,请使用setenforce permissive设置,并使用chcon设置正确的SELinux上下文。


这个方法在我的 Oracle OCI VM 实例上解决了问题。 - Alexander

0

在使用 Podman 生成 systemd 单元文件时,我遇到了这个错误。

出现此错误是因为 selinux 阻止了文件的正确读取。我发现有两种解决方案。

  1. 将目录设置为单元文件的 systemd 服务位置,使用 cd /etc/systemd/system。然后直接在此处使用 podman generate 创建文件。这似乎可以被 selinux 接受而没有问题。

  2. 使用 podman generate 生成 systemd 单元文件,并将文件复制到 /etc/systemd/system。然后需要运行 /sbin/restorecon -v /etc/systemd/system/container-<your container name>.service 来使 selinux 重置该文件的安全上下文。


0
当你遇到这种情况时,可以尝试获取它所指的文件。例如,我在使用ContainerD时也遇到了同样的问题。我所要做的就是去另一台服务器上获取文件“cat /lib/systemd/system/containerd.service”。在你的文件系统中,这个文件必须存在(可能在你的备份中)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接