O serviço Debian não está iniciando o arquivo corretamente na inicialização

O serviço Debian não está iniciando o arquivo corretamente na inicialização

Eu tenho um arquivo chamado botstart.servicecom /etc/systemd/systemeste conteúdo:

[Unit]
Description=Start all discord bots (AntiSpam, AutoChat, Nyoko, Helper) and the lavalink server.

[Service]
ExecStart=/bin/bash /home/scripts/start.sh

[Install]
WantedBy=multi-user.target

Comecei com systemctl enable botstart e dizia que estava habilitado. Reiniciei meu VPS, mas o script não foi executado. Eu fiz systemctl status botstarte mostrou isso:

root@Hetzner-01:~# systemctl status botstart
● botstart.service - Start all discord bots (AntiSpam, AutoChat, Nyoko, Helper)
   Loaded: loaded (/etc/systemd/system/botstart.service; enabled; vendor preset:
   Active: inactive (dead) since Wed 2021-10-27 01:37:10 CEST; 50s ago
  Process: 481 ExecStart=/bin/bash /home/scripts/start.sh (code=eited, status=0
 Main PID: 481 (code=existed, status=0/SUCCESS)

Oct 27 01:37:07 Hetzner-01 systemd[1]: STarted Start all discord bots (antiSpam,
Oct 27 01:37:10 Hetzner-01 bash[481]: Started all bots
Oct 27 01:37:10 Hetzner-01 systemd[1]: botstart.service: Succeeded.
lines 1-9/9 (END)...skipping...
● botstart.service - Start all discord bots (AntiSpam, AutoChat, Nyoko, Helper) and the lavalink server.
   Loaded: loaded (/etc/systemd/system/botstart.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Wed 2021-10-27 01:37:10 CEST; 50s ago
  Process: 481 ExecStart=/bin/bash /home/scripts/start.sh (code=eited, status=0/SUCCESS)
 Main PID: 481 (code=existed, status=0/SUCCESS)

Se eu executar o script manualmente, ele funcionará, mas de alguma forma não como um serviço, mas o serviço será executado e o script será executado (é o que o status do serviço está me dizendo). Alguém sabe por quê? Este é o código do script:

screen -dmS antispam bash -c "cd /home/AntiSpam; python3.8 main.py"
screen -dmS autochat bash -c "cd /home/AutoChat; python3.8 main.py"
screen -dmS helper bash -c "cd /home/Helper; python3.8 main.py"
screen -dmS lavalink bash -c "cd /home/Lavalink; python3.8 main.py"
sleep 3
screen -dmS nyoko bash -c "cd /home/Nyoko; python3.8 main.py"
echo "Started all bots"

Responder1

Na sua [Service]seção, você não definiu explicitamente um arquivo Type=. Isso significa que o padrão será Type=simple.

A página de manual diz:

Se definido como simples, o gerenciador de serviço considerará a unidade iniciada imediatamente após o processo de serviço principal ter sido interrompido. Espera-se que o processo configurado com ExecStart= seja o processo principal do serviço....

Resumindo, seu script é o processo principal. Ele inicia vários processos e depois sai. systemdvê a saída do seu processo principal e, em seguida, procede à limpeza dos processos filhos que não têm mais um pai.

Em vez disso você quer Type=forking.

Se definido como forking, espera-se que o processo configurado com ExecStart= chame fork() como parte de sua inicialização. Espera-se que o processo pai seja encerrado quando a inicialização for concluída e todos os canais de comunicação estiverem configurados. O processo filho continua a ser executado como o processo de serviço principal e o gerente de serviço considerará a unidade iniciada quando o processo pai for encerrado. Este é o comportamento dos serviços UNIX tradicionais. Se esta configuração for usada, é recomendável usar também a opção PIDFile=, para que o systemd possa identificar com segurança o processo principal do serviço.

Nesse caso, seus processos filhos poderão continuar vivos, mesmo após o término do script. Se você adicionar Type=forking, as coisas funcionarão melhor para você.


Observe que existem alguns outros problemas com seu design. Se a única alteração feita for Type=forking, você ainda terá alguns problemas:

  • Se um dos processos terminar, o systemd pode decidir ou não qual é o MainPID e considerar todo o seu serviço inactive (dead). Escrever para a PIDFile=pode ajudar com isso, mas suspeito que você não pretende que nenhum desses processos seja o MainPID.
  • Se um processo falhar, systemdnão poderá reportar um estado de falha. Não está claro o que deve acontecer com os outros processos.

Recomendação 1: divida cada processo em seu próprio serviço. Então Type=simplefuncionará. Dessa forma, se um serviço falhar, você poderá detectá-lo e operá-lo de maneira confiável, sem afetar os outros bots.

Recomendação 2: Adicione Restart=on-failure. Isso permitirá que um serviço com falha seja reiniciado automaticamente (sem necessidade de intervenção humana).

Recomendação 3: Não ligue para bashquais chamadas screenpara quais chamadas python3. Basta ligar diretamente para python. screené uma solução alternativa que não é necessária em um systemdambiente.

Recomendação 4: Para implementar isso sleep 3, você pode usar umExecStartPre=

Seguindo essas recomendações, nyoko.serviceficaria assim:

[Unit]
Description=Nyoko discord bot

[Service]
WorkingDirectory=/home/Nyoko
ExecStartPre=/usr/bin/sleep 3
ExecStart=/usr/bin/python3 /home/Nyoko/main.py
Restart=on-failure

[Install]
WantedBy=multi-user.target

Recomendação 5: sleepnão é muito confiável. Num dia bom, perde 3 segundos. Num dia ruim, não é suficiente e seu serviço irá falhar. Considere adicionar itens After=lavalink.serviceà sua [Unit]seção para garantir lavalink.serviceque seja iniciado antes de algo que dependa dela. Se lavalinkhouver algum tipo de sinal para mostrar que ele foi iniciado (o arquivo foi criado ou o soquete foi aberto), você poderá acioná-lo.

informação relacionada