Confuso dalle voci ExecStartPre nel file di unità systemd


23

Ho un servizio systemd in cui è necessario creare una directory /run, ma altrimenti eseguito come utente non root. Da un esempio di blog, ho derivato la seguente soluzione:

[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 è nelle 3 righe che seguono il commento. Apparentemente ExecStartPreverrà eseguito come root in questo modo, ma ExecStartverrà eseguito come l'utente specificato.

Ciò ha portato a 3 domande:

  1. Cosa fa -di fronte al /bin/mkdir? Non so perché sia ​​lì o cosa faccia.
  2. Quando sono presenti più ExecStartPrefile in un file di unità, vengono semplicemente eseguiti in serie nell'ordine in cui si trovano nel file di unità? O qualche altro metodo?
  3. È davvero la migliore tecnica per raggiungere il mio obiettivo di creare la directory di esecuzione in modo che l'utente non root possa utilizzarla?

Il motivo per cui ExecStartPreviene eseguito come root è la PermissionsStartOnly=truedirettiva. Limita la Userdirettiva solo al ExecStartcomando. Vedi freedesktop.org/software/systemd/man/systemd.service.html
cayhorstmann

Risposte:


30

Per qualsiasi domanda su un sistema e le direttive, è possibile utilizzare man systemd.directivesper cercare la pagina man che documenta la direttiva. Nel caso di ExecStartPre=, lo troverai documentato in man systemd.service.

Lì nei documenti per ExecStartPre=, troverai spiegato che il principale "-" viene utilizzato per notare che l'errore è tollerato per questi comandi. In questo caso, è tollerato se /run/thingesiste già.

I documenti lì spiegano anche che "sono consentite più righe di comando e i comandi vengono eseguiti uno dopo l'altro, in serie".

Un miglioramento del tuo metodo di pre-creazione della directory non è renderlo scrivibile in tutto il mondo quando hai solo bisogno che sia scrivibile da un determinato utente. Autorizzazioni più limitate sarebbero ottenute con:

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

Ciò rende la directory di proprietà e completamente accessibile da un determinato utente.


Risposta fantastica, grazie per il suggerimento systemd.directives, trovo sempre difficile trovare systemd dove andare. Questo aiuta.
Travis Griggs

1
Probabilmente si dovrebbe coprire RuntimeDirectorye RuntimeDirectoryModetroppo.
JdeBP

2

Risposta a # 3:

Consulta le direttive RuntimeDirectory=& RuntimeDirectoryMode=. Documenti completi qui . Ma in sintesi (leggera modifica al testo, ma essence dovrebbe rimanere):

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.

Quindi, per sfruttarlo, questo dovrebbe fare il trucco:

[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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.