Posso usar o systemd para iniciar e parar um serviço com base na presença de um arquivo?

9

Minha configuração até agora é:

foo.path

[Path] 
PathExists=/tmp/foo.path

[Install] 
WantedBy=multi.user.target

foo.service

[Unit]
Description=Matt Test
BindsTo=foo.path

[Service]
ExecStart=/bin/sh /home/mpekar/bin/foo.sh 
PIDFile=/run/foo.pid

Isso funciona bem ao iniciar, mas o foo.service não será eliminado quando o /tmp/foo.path for removido. Existe alguma maneira de fazer o systemd fazer isso ou simplesmente não é a ferramenta apropriada para o trabalho?

mpr
fonte

Respostas:

4

Eu tentaria isso. Crie um serviço adicional usando PathChanged:

foo-stop.path

[Path] 
PathChanged=/tmp/foo.path

[Install] 
WantedBy=multi.user.target

Em seguida, crie: foo-stop.service

Faça com que o script "ExecStart" verifique se /tmp/foo.pathfoi excluído (pois o PathChanged também pode disparar em outras alterações). Se o caminho foi removido, faça a chamada de script /bin/systemctl stop foo.

Mark Stosberg
fonte
1
Vou seguir em frente e aceitar isso até que o systemd ofereça uma opção explícita para fazer o mesmo.
mpr
0

Se você conseguir eliminar o processo vinculado ao PIDFile (/run/foo.pid) quando o /tmp/foo.path for removido (por exemplo, ambos como ações no script de desligamento do serviço), então sim.

Consegui isso em um Tomcat executando <= RHEL-7.7 com um serviço de bifurcação, incluindo uma ação ExecStartPost que anota o conteúdo do aplicativo pidfile (catalina.pid) no caminho do serviço PIDFile. Um "PathExists" no arquivo .path correspondente rastreia a aparência desse catalina.pid para ligar o serviço systemd quando o usuário (no meu caso, sem privilégios) chama o script de inicialização. Quando o usuário inicia o desligamento, o pidfile do aplicativo é removido, o PID (também sem privilégios) morre normalmente e o systemd para o serviço como uma conseqüência da supervisão do pd do systemd.

poc.service:

[nouser@nohost system]# cat poc.service
# . . .
[Unit]
After=network.target
After=%p.path
Wants=%p.path
# . . . 
[Service]
Type=forking
Environment="%p_APPLICATION_PID_FILE=/opt/%p/logs/catalina.pid"
PIDFile=/var/run/%p.pid
ExecStart=/bin/sh -c '/path/to/tomcat/control/script/invoked/with/su/hypen start'
ExecStartPost=/bin/sh -c 'cat ${%p_APPLICATION_PID_FILE} > $(systemctl show %n -p PIDFile|cut -f2- -d"=")'
ExecStop=/bin/sh -c '/path/to/tomcat/control/script/invoked/with/su/hypen stop'
# . . .

poc.path:

[nouser@nohost system]# cat poc.path
# . . .
[Path]
PathExists=/opt/%p/logs/catalina.pid
# . . .

Dessa forma, também me serviu para aplicativos de inicialização de primavera. Mas, como eles nasceram pendurados em um processo de bash, tive que interromper imediatamente o processo pai para forçar o PID 1 a ser o pai do aplicativo. Caso contrário, o journalctl mostra uma mensagem "* .service: processo de supervisão XXXXX, que não é nosso filho. Provavelmente, não perceberemos quando ele sair." E, no final, o serviço systemd não para na ação de desligamento do usuário.

Pere Moltó
fonte