web-dev-qa-db-fra.com

Confus par les entrées ExecStartPre dans le fichier d'unité systemd

J'ai un service systemd qui doit créer un répertoire dans /run, mais sinon exécuté en tant qu'utilisateur non root. À partir d'un exemple de blog, j'ai dérivé la solution suivante:

[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 magie est dans les 3 lignes qui suivent le commentaire. Apparemment, les ExecStartPre s'exécuteront en tant que root de cette façon, mais les ExecStart s'exécuteront en tant qu'utilisateur spécifié.

Cela a conduit à 3 questions cependant:

  1. Que fait le - faire devant le /bin/mkdir? Je ne sais pas pourquoi il est là ou ce qu'il fait.
  2. Lorsqu'il y a plusieurs ExecStartPre dans un fichier d'unité, sont-ils simplement exécutés en série dans l'ordre où ils se trouvent dans le fichier d'unité? Ou une autre méthode?
  3. Est-ce réellement la meilleure technique pour atteindre mon objectif de créer le répertoire d'exécution afin que l'utilisateur non root puisse l'utiliser?
24
Travis Griggs

Pour toute question sur les directives systemd, vous pouvez utiliser man systemd.directives pour rechercher la page de manuel qui documente la directive. Dans le cas de ExecStartPre=, vous le trouverez documenté dans man systemd.service.

Là dans les documents pour ExecStartPre=, vous constaterez qu'il est expliqué que le premier "-" est utilisé pour noter que l'échec est toléré pour ces commandes. Dans ce cas, il est toléré si /run/thing existe déjà.

Les documents expliquent également que "plusieurs lignes de commande sont autorisées et les commandes sont exécutées les unes après les autres, en série".

Une amélioration de votre méthode de pré-création du répertoire n'est pas de le rendre accessible en écriture mondiale lorsque vous avez seulement besoin qu'il soit accessible en écriture par un utilisateur particulier. Des autorisations plus limitées seraient accomplies avec:

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

Cela rend le répertoire détenu par et entièrement accessible à partir d'un utilisateur particulier.

33
Mark Stosberg

Réponse à # 3:

Vérifiez RuntimeDirectory= & RuntimeDirectoryMode= directives. Documents complets ici . Mais en résumé (légère modification du texte, mais l'essence doit rester):

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.

Donc, pour tirer parti de cela, cela devrait faire l'affaire:

[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
3
Jeremy Davis