Verwirrt durch ExecStartPre-Einträge in der System-Unit-Datei

23

Ich besitze einen systemd-Dienst, in dem ein Verzeichnis erstellt werden muss /run, der jedoch ansonsten als Nicht-Root-Benutzer ausgeführt wird. Aus einem Blog-Beispiel habe ich die folgende Lösung abgeleitet:

[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

Die Magie steckt in den 3 Zeilen, die dem Kommentar folgen. Anscheinend ExecStartPrelaufen die 's auf diese Weise als root, aber die ExecStartlaufen als der angegebene Benutzer.

Dies hat jedoch zu 3 Fragen geführt:

  1. Was macht der -vor dem /bin/mkdir? Ich weiß nicht, warum es da ist oder was es tut.
  2. Befinden sich mehrere ExecStartPrein einer Gerätedatei, werden sie nur in der Reihenfolge seriell ausgeführt, in der sie in der Gerätedatei gefunden wurden? Oder eine andere Methode?
  3. Ist dies tatsächlich die beste Methode, um mein Ziel zu erreichen, das Ausführungsverzeichnis so zu erstellen, dass der Benutzer ohne Rootberechtigung es verwenden kann?
Travis Griggs
quelle
Der Grund, warum das ExecStartPreals root ausgeführt wird, ist die PermissionsStartOnly=trueDirektive. Es beschränkt die UserDirektive nur auf den ExecStartBefehl. Siehe freedesktop.org/software/systemd/man/systemd.service.html
cayhorstmann

Antworten:

30

Bei Fragen zu systemd-Direktiven können Sie man systemd.directivesdie Manpage aufrufen, die die Direktive dokumentiert. Im Falle von ExecStartPre=finden Sie es dokumentiert in man systemd.service.

Dort in docs for ExecStartPre=wird erklärt, dass das führende "-" verwendet wird, um darauf hinzuweisen, dass Fehler für diese Befehle toleriert werden. In diesem Fall wird es toleriert, wenn es /run/thingbereits existiert.

Die dortigen Dokumente erklären auch, dass "mehrere Befehlszeilen zulässig sind und die Befehle nacheinander seriell ausgeführt werden".

Eine Verbesserung Ihrer Methode zum Vorerstellen des Verzeichnisses besteht darin, dass es nicht für die ganze Welt beschreibbar ist, wenn Sie nur benötigen, dass es von einem bestimmten Benutzer beschrieben werden kann. Eingeschränktere Berechtigungen würden erreicht werden mit:

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

Dadurch ist das Verzeichnis im Besitz eines bestimmten Benutzers und für diesen vollständig zugänglich.

Mark Stosberg
quelle
Tolle Antwort, danke für den Hinweis von systemd.directives. Ich finde es immer schwierig, herauszufinden, wohin ich gehen soll. Das hilft.
Travis Griggs
1
Sie sollten wahrscheinlich decken RuntimeDirectoryund RuntimeDirectoryModeauch.
JdeBP
2

Antwort auf # 3:

Schauen Sie sich die RuntimeDirectory=& RuntimeDirectoryMode=Direktiven an. Vollständige Dokumente hier . Aber in der Zusammenfassung (geringfügige Änderung des Textes, aber das Wesentliche sollte bleiben):

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.

Um das zu nutzen, sollte dies der Trick sein:

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