Confundido pelas entradas ExecStartPre no arquivo de unidade systemd


23

Eu tenho um serviço systemd que precisa criar um diretório /run, mas executado como um usuário não raiz. De um exemplo de blog, deduzi a seguinte solução:

[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

A mágica está nas 3 linhas que seguem o comentário. Aparentemente, os ExecStartPrearquivos serão executados como root dessa maneira, mas ExecStartserão executados como o usuário especificado.

Isso levou a três perguntas:

  1. O que -faz na frente do /bin/mkdir? Não sei por que está lá ou o que faz.
  2. Quando existem múltiplos ExecStartPreem um arquivo de unidade, eles são executados apenas em série na ordem em que são encontrados no arquivo de unidade? Ou algum outro método?
  3. Essa é realmente a melhor técnica para atingir meu objetivo de criar o diretório de execução para que o usuário não root possa usá-lo?

A razão pela qual a ExecStartPreexecução é raiz é a PermissionsStartOnly=truediretiva. Ele restringe a Userdiretiva apenas ao ExecStartcomando. Veja freedesktop.org/software/systemd/man/systemd.service.html
cayhorstmann

Respostas:


30

Para qualquer dúvida sobre as diretivas de um systemd, você pode usar man systemd.directivespara pesquisar a página de manual que documenta a diretiva. No caso de ExecStartPre=, você o encontrará documentado man systemd.service.

Lá nos documentos para ExecStartPre=, você descobrirá que o "-" inicial é usado para observar que a falha é tolerada para esses comandos. Nesse caso, é tolerado se /run/thingjá existir.

Os documentos também explicam que "várias linhas de comando são permitidas e os comandos são executados um após o outro, em série".

Um aprimoramento do seu método de pré-criação do diretório não o torna gravável no mundo quando você precisa que ele seja gravável apenas por um usuário específico. Permissões mais limitadas seriam realizadas com:

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

Isso torna o diretório de propriedade e totalmente acessível a partir de um usuário específico.


Resposta incrível, obrigado pela dica systemd.directives, sempre acho difícil para o sistema descobrir para onde ir. Isso ajuda.
Travis Griggs

1
Você provavelmente deve cobrir RuntimeDirectorye RuntimeDirectoryModetambém.
JdeBP # 01/17

2

Resposta para # 3:

Confira as diretivas RuntimeDirectory=& RuntimeDirectoryMode=. Documentos completos aqui . Mas em resumo (pequena modificação no texto, mas a essência deve 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.

Então, para alavancar isso, isso deve fazer o truque:

[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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.