与systemd单位文件中的ExecStartPre条目混淆


23

我有一个systemd服务,需要在中创建目录/run,但要以非root用户身份运行。从一个博客示例中,我得出了以下解决方案:

[Unit]
Description=Startup Thing

[Service]
Type=oneshot
ExecStart=/usr/bin/python3 -u /opt/thing/doStartup
WorkingDirectory=/opt/thing
StandardOutput=journal
User=thingUser
# Make sure the /run/thing directory exists
PermissionsStartOnly=true
ExecStartPre=-/bin/mkdir -p /run/thing
ExecStartPre=/bin/chmod -R 777 /run/thing

[Install]
WantedBy=multi-user.target

神奇之处在于注释后的3行。显然,ExecStartPre的将以root身份运行,但是ExecStart将会以指定的用户身份运行。

但是,这导致了三个问题:

  1. -前面做什么/bin/mkdir?我不知道为什么它在那里或做什么。
  2. ExecStartPre一个单位文件中有多个时,它们是否只是按照在单位文件中找到的顺序依次运行?还是其他方法?
  3. 这实际上是实现我创建运行目录的目标的最佳技术,以便非root用户可以使用它吗?

ExecStartPre以root身份运行的原因是PermissionsStartOnly=true指令。它User仅将指令限制为ExecStart命令。参见freedesktop.org/software/systemd/man/systemd.service.html
cayhorstmann,2017年

Answers:


30

对于有关systemd指令的任何问题,您可以man systemd.directives用来查找记录该指令的手册页。如果是ExecStartPre=,您会发现它记录在中man systemd.service

在的文档中ExecStartPre=,您会发现它解释了前导“-”用于表示这些命令可以容忍失败。在这种情况下,可以容忍它/run/thing已经存在。

那里的文档还解释说:“允许使用多个命令行,并且一个接一个地依次执行命令。”

当您只需要特定用户可写的目录时,对预创建目录的方法的一项改进就是不能将其设置为可写。更有限的权限将通过以下方式完成:

 ExecStartPre=-/bin/chown thingUser /run/thing
 ExecStartPre=-/bin/chmod 700       /run/thing

这使得该目录归特定用户所有,并可以从中完全访问。


很棒的答案,谢谢您的systemd.directives提示,我总是觉得systemd很难弄清楚该去哪里。有帮助。
Travis Griggs

1
你或许应该涵盖RuntimeDirectoryRuntimeDirectoryMode太。
JdeBP '17

2

回答#3:

查看RuntimeDirectory=RuntimeDirectoryMode=指令。完整的文档在这里。但总而言之(对文本稍作修改,但本质上应保留):

RuntimeDirectory=

       This option take a whitespace-separated list of directory names. The 
       specified directory names must be relative, and may not include "..". If
       set, one or more directories by the specified names will be created
       (including their parents) below /run (for system services) or below 
       $XDG_RUNTIME_DIR (for user services) when the unit is started. Also, the  
       $RUNTIME_DIRECTORY environment variable is defined with the full path of 
       directories. If multiple directories are set, then in the environment 
       variable the paths are concatenated with colon (":").

       The innermost subdirectories are removed when the unit is stopped. It is 
       possible to preserve the specified directories in this case if 
       RuntimeDirectoryPreserve= is configured to restart or yes. The innermost 
       specified directories will be owned by the user and group specified in 
       User= and Group=.

       If the specified directories already exist and their owning user or group 
       do not match the configured ones, all files and directories below the 
       specified directories as well as the directories themselves will have their 
       file ownership recursively changed to match what is configured. As an 
       optimization, if the specified directories are already owned by the right 
       user and group, files and directories below of them are left as-is, even if 
       they do not match what is requested. The innermost specified directories 
       will have their access mode adjusted to the what is specified in 
       RuntimeDirectoryMode=.

       Use RuntimeDirectory= to manage one or more runtime directories for the 
       unit and bind their lifetime to the daemon runtime. 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).


RuntimeDirectoryMode=

       Specifies the access mode of the directories specified in 
       RuntimeDirectory= as an octal number. Defaults to 0755. See "Permissions" 
       in path_resolution(7) for a discussion of the meaning of permission bits.

因此,利用这一点,就可以达到目的:

[Unit]
Description=Startup Thing

[Service]
Type=oneshot
ExecStart=/usr/bin/python3 -u /opt/thing/doStartup
WorkingDirectory=/opt/thing
StandardOutput=journal
User=thingUser
# Make sure the /run/thing directory exists
PermissionsStartOnly=true
RuntimeDirectory=thing
RuntimeDirectoryMode=0777

[Install]
WantedBy=multi-user.target
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.