systemd:mkdir和ExecStartPre的权限问题


37

我有这个(缩短)systemd服务文件的问题:

[Unit]
Description=control FOO daemon
After=syslog.target network.target

[Service]
Type=forking
User=FOOd
Group=FOO
ExecStartPre=/bin/mkdir -p /var/run/FOOd/
ExecStartPre=/bin/chown -R FOOd:FOO /var/run/FOOd/
ExecStart=/usr/local/bin/FOOd -P /var/run/FOOd/FOOd.pid
PIDFile=/var/run/FOOd/FOOd.pid

[Install]
WantedBy=multi-user.target

假设FOOd为用户名,FOO为组名,这对于我的守护程序已经存在/usr/local/bin/FOOd

我需要创建目录/var/run/FOOd/启动守护进程之前/usr/local/bin/FOOd通过# systemctl start FOOd.service。这失败,因为由于权限的原因mkdir无法创建目录:

...
Jun 03 16:18:49 PC0515546 mkdir[2469]: /bin/mkdir: cannot create directory /var/run/FOOd/: permission denied
Jun 03 16:18:49 PC0515546 systemd[1]: FOOd.service: control  process exited, code=exited status=1
...

为什么mkdir在ExecStartPre上失败,我该如何解决?(不,我不能将sudo用于mkdir ...)


FYI:我使用Debian 8
马特

您能将错误消息翻译成英文吗?
2015年

1
... Jun 03 16:18:49 PC0515546 mkdir [2469]:/ bin / mkdir:无法创建目录/ var / run / FOOd /:没有权限Jun 03 16:18:49 PC0515546 systemd [1] :FOOd.service:控制进程已退出,代码=退出状态= 1 ...
马特

Answers:


56

您需要添加

PermissionsStartOnly=true

[Service]。您的用户FOOd当然无权在中创建目录/var/run。引用手册页:

接受布尔参数。如果为true,则使用User =和类似选项配置的与权限相关的执行选项(有关更多信息,请参见systemd.exec(5))仅适用于以ExecStart =开始的进程,而不适用于其他ExecStartPre = ,ExecStartPost =,ExecReload =,ExecStop =和ExecStopPost =命令。如果为false,则该设置以相同的方式应用于所有已配置的命令。默认为false。


1
太好了,正是我想要的。
罗伯特

2
此选项使命令ExecReload=以root特权运行。这可能不是您想要的。
Rockallite

@Rockallite就是我从字面上引用的文档所说的,是的。
embik

2
PermissionsStartOnly不推荐使用。参考:github.com/NixOS/nixpkgs/issues/53852现在怎么做?
adrelanos

2
@adrelanos现在,+在之后立即添加一个ExecStartPre=。例如ExecStartPre=+/bin/mkdir test
Jamie Scott

28

这不是解释或解决权限问题的答案,但我认为您应该只使用systemds RuntimeDirectory选项。引用手册页

RuntimeDirectory=, RuntimeDirectoryMode=
       Takes a list of directory names. If set, one or more directories by
       the specified names will be created below /run (for system
       services) or below $XDG_RUNTIME_DIR (for user services) when the
       unit is started, and removed when the unit is stopped. The
       directories will have the access mode specified in
       RuntimeDirectoryMode=, and will be owned by the user and group
       specified in User= and Group=. Use this to manage one or more
       runtime directories of the unit and bind their lifetime to the
       daemon runtime. The specified directory names must be relative, and
       may not include a "/", i.e. must refer to simple directories to
       create or remove. This is particularly useful for unprivileged
       daemons that cannot create runtime directories in /run due to lack
       of privileges, and to make sure the runtime directory is cleaned up
       automatically after use. For runtime directories that require more
       complex or different configuration or lifetime guarantees, please
       consider using tmpfiles.d(5).

因此,您要做的就是将服务文件更改为:

[Unit]
Description=control FOO daemon
After=syslog.target network.target

[Service]
Type=forking
User=FOOd
Group=FOO
RuntimeDirectory=FOOd
RuntimeDirectoryMode=$some-mode
ExecStart=/usr/local/bin/FOOd -P /run/FOOd/FOOd.pid
PIDFile=/run/FOOd/FOOd.pid

[Install]
WantedBy=multi-user.target

谢谢谢谢。可悲的是,OpenVPN Ubuntu软件包中缺少该功能!!
BaseZen

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.