systemd: problema de permissão com mkdir e ExecStartPre

37

Estou com um problema com este arquivo de serviço systemd (reduzido):

[Unit]
Description=control FOO daemon
After=syslog.target network.target

[Service]
Type=forking
User=FOOd
Group=FOO
ExecStartPre=/bin/mkdir -p /var/run/FOOd/
ExecStartPre=/bin/chown -R FOOd:FOO /var/run/FOOd/
ExecStart=/usr/local/bin/FOOd -P /var/run/FOOd/FOOd.pid
PIDFile=/var/run/FOOd/FOOd.pid

[Install]
WantedBy=multi-user.target

Seja FOOd o nome de usuário e FOO o nome do grupo, que já existe para o meu daemon /usr/local/bin/FOOd.

Preciso criar o diretório /var/run/FOOd/antes de iniciar o processo daemon /usr/local/bin/FOOdvia # systemctl start FOOd.service. Isso falha, porque o mkdir não pode criar o diretório devido às permissões:

...
Jun 03 16:18:49 PC0515546 mkdir[2469]: /bin/mkdir: cannot create directory /var/run/FOOd/: permission denied
Jun 03 16:18:49 PC0515546 systemd[1]: FOOd.service: control  process exited, code=exited status=1
...

Por que o mkdir falha no ExecStartPre e como posso corrigi-lo? (E não, não posso usar o sudo para mkdir ...)

Matt
fonte
FYI: Estou usando o Debian 8
Matt
Você pode traduzir a mensagem de erro para o inglês?
Thushi
11
... Jun 03 16:18:49 PC0515546 mkdir [2469]: / bin / mkdir: o diretório / var / run / FOOd / não pode ser criado: sem permissão Jun 03 16:18:49 PC0515546 systemd [1] : FOOd.service: processo de controle saiu, code = saiu status = 1 ...
Matt

Respostas:

56

Você precisa adicionar

PermissionsStartOnly=true

para [Service] . FOOdÉ claro que seu usuário não está autorizado a criar um diretório no /var/run. Para citar a página de manual:

Adota um argumento booleano. Se true, as opções de execução relacionadas à permissão, conforme configuradas com User = e opções semelhantes (consulte systemd.exec (5) para obter mais informações), são aplicadas apenas ao processo iniciado com ExecStart = e não aos vários outros ExecStartPre = , ExecStartPost =, ExecReload =, ExecStop = e ExecStopPost = comandos. Se falso, a configuração é aplicada a todos os comandos configurados da mesma maneira. O padrão é false.

embik
fonte
11
Maravilhoso, exatamente o que eu estava procurando.
robert
2
Esta opção faz com que os comandos sejam ExecReload=executados com privilégios de root. Pode não ser o que você deseja.
Rockallite 16/03/19
@Rockallite é o que a documentação que citei diz literalmente, sim.
embik
2
PermissionsStartOnlyfoi preterido. Referência: github.com/NixOS/nixpkgs/issues/53852 Como fazer isso agora?
adrelanos
2
@adrelanos Agora, adicione um +imediatamente depois ExecStartPre=. Por exemploExecStartPre=+/bin/mkdir test
Jamie Scott
28

Esta não é uma resposta que explique ou corrija o problema de permissão, mas acho que você deve usar a opção systemds RuntimeDirectory. Citando a página de manual :

RuntimeDirectory=, RuntimeDirectoryMode=
       Takes a list of directory names. If set, one or more directories by
       the specified names will be created below /run (for system
       services) or below $XDG_RUNTIME_DIR (for user services) when the
       unit is started, and removed when the unit is stopped. The
       directories will have the access mode specified in
       RuntimeDirectoryMode=, and will be owned by the user and group
       specified in User= and Group=. Use this to manage one or more
       runtime directories of the unit and bind their lifetime to the
       daemon runtime. The specified directory names must be relative, and
       may not include a "/", i.e. must refer to simple directories to
       create or remove. 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).

Então, tudo que você precisa fazer é alterar seu arquivo de serviço para:

[Unit]
Description=control FOO daemon
After=syslog.target network.target

[Service]
Type=forking
User=FOOd
Group=FOO
RuntimeDirectory=FOOd
RuntimeDirectoryMode=$some-mode
ExecStart=/usr/local/bin/FOOd -P /run/FOOd/FOOd.pid
PIDFile=/run/FOOd/FOOd.pid

[Install]
WantedBy=multi-user.target
Wieland
fonte
Obrigado, obrigado. Infelizmente faltando no pacote OpenVPN Ubuntu !!
BaseZen