Confundido por las entradas ExecStartPre en el archivo de unidad systemd


23

Tengo un servicio systemd que necesita crear un directorio /run, pero que se ejecuta como usuario no root. De un ejemplo de blog, obtuve la siguiente solución:

[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

La magia está en las 3 líneas que siguen al comentario. Aparentemente, los ExecStartPre's se ejecutarán como root de esta manera, pero ExecStartse ejecutarán como el usuario especificado.

Sin embargo, esto ha llevado a 3 preguntas:

  1. ¿Qué hace el -frente de la /bin/mkdir? No sé por qué está allí o qué hace.
  2. Cuando hay múltiples ExecStartPre's en un archivo de unidad, ¿se ejecutan en serie en el orden en que se encuentran en el archivo de unidad? ¿O algún otro método?
  3. ¿Es esta la mejor técnica para lograr mi objetivo de crear el directorio de ejecución para que el usuario no root pueda usarlo?

La razón por la que se ExecStartPreejecuta como root es la PermissionsStartOnly=truedirectiva. Restringe la Userdirectiva solo al ExecStartcomando. Consulte freedesktop.org/software/systemd/man/systemd.service.html
cayhorstmann el

Respuestas:


30

Para cualquier pregunta sobre las directivas de systemd, puede usar man systemd.directivespara buscar la página del manual que documenta la directiva. En el caso de ExecStartPre=, lo encontrará documentado en man systemd.service.

Allí en los documentos para ExecStartPre=, encontrará explicado que el principal "-" se utiliza para notar que se tolera la falla para estos comandos. En este caso, se tolera si /run/thingya existe.

Los documentos allí también explican que "se permiten varias líneas de comando y los comandos se ejecutan uno tras otro, en serie".

Una mejora en su método de creación previa del directorio es que no se puede escribir en todo el mundo cuando solo necesita que un usuario en particular lo pueda escribir. Se lograrían permisos más limitados con:

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

Eso hace que el directorio sea propiedad y esté completamente accesible desde un usuario en particular.


Impresionante respuesta, gracias por la sugerencia de systemd.directives, siempre encuentro que systemd es difícil de averiguar a dónde ir. Eso ayuda.
Travis Griggs

1
Probablemente deberías cubrir RuntimeDirectoryy RuntimeDirectoryModetambién.
JdeBP

2

Respuesta al # 3:

Echa un vistazo a las directivas RuntimeDirectory=& RuntimeDirectoryMode=. Documentos completos aquí . Pero en resumen (ligera modificación del texto, pero la esencia debe permanecer):

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.

Entonces, para aprovechar eso, esto debería hacer el truco:

[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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.