Executar enquanto verdadeiro no script systemd

8

Eu tenho um script bash essencialmente executando isso:

#!/bin/bash

[...]

 while true; do
         str="broadcast "`randArrayElement "messages[@]"`
         server_send_message $str
         sleep $interval
 done

Agora eu quero executar isso como um serviço systemd, meu script de serviço fica assim:

[Unit]
Description=Announcer
After=network.target

[Service]
ExecStart=/usr/local/bin/somescript &; disown
ExecStop=/usr/bin/kill -9 `cat /tmp/somescript.pid`
Type=forking
PIDFile=/tmp/somescript.pid

[Install]
WantedBy=default.target

Infelizmente, quando eu executo esse serviço, service somescript startele está funcionando, mas, devido ao loop while true, meu terminal está preso ao iniciar o script:

 somescript.service - somescript service
   Loaded: loaded (/etc/systemd/system/somescript.service; disabled; vendor preset: enabled)
   Active: activating (start) since Wed 2016-08-17 12:22:34 CEST; 43s ago
  Control: 17395 (somescript)
   CGroup: /system.slice/somescript.service
           ├─17395 /bin/bash /usr/local/bin/somescript &; disown
           └─17409 sleep 600

Como posso executar este script como um serviço sem ficar preso no loop "inicial" / while true?

Flatron
fonte

Respostas:

8

Você precisa deixar o systemd funcionar para você. Deixe-o lidar com o garfo no início e com o fim do processo. Por exemplo, substitua sua peça de serviço por

[Service]
Type=simple
ExecStart=/usr/local/bin/somescript
PIDFile=/tmp/somescript.pid

então você pode usar systemctl start, statuse stop. Você deve se lembrar que as linhas no systemd NÃO são interpretadas pelo shell, portanto, por exemplo, o seu &;é meramente passado como outro parâmetro de 2 caracteres para o seu script.

meuh
fonte
Ok, obrigado, eu fiz as alterações. Infelizmente, o script ainda trava ao tentar iniciá-lo como antes.
Flatron
1
Você se lembrou de fazer sudo systemctl daemon-reload?
Meu 17/08/16
Você conhece esses momentos em que pensa que já fez algo que não fez? Obrigado, funciona! :)
Flatron
1

Dependendo dos seus requisitos, considere substituir seu loop por uma configuração de timer do sistema. Ele não iniciará o serviço duas vezes, mesmo que server_send_message demore mais que "OnUnitActiveSec":

somescript.timer

[Unit]
Description=Announce every minute

[Timer]
OnUnitActiveSec=1m
AccuracySec=10s
Unit=somescript.service

[Install]
WantedBy=default.target

parte do serviço somescript.service:

[Service]
Type=oneshot
ExecStart=/usr/bin/sh -c 'str="broadcast "`randArrayElement "messages[@]"`; server_send_message $str'
Gerrit Griebel
fonte