Estou usando o CentOS 7. Como descubro por que um serviço está falhando ao iniciar? Eu criei este serviço
[rails@server ~]$ sudo cat /usr/lib/systemd/system/nodejs.service
[Unit]
Description=nodejs server
[Service]
User=rails
Group=rails
ExecStart=/home/rails/NodeJSserver/start.sh
ExecStop=/home/rails/NodeJSserver/stop.sh
[Install]
WantedBy=multi-user.target
O arquivo aponta para isso
[rails@server ~]$ cat /home/rails/NodeJSserver/start.sh
#!/bin/bash
forever start /home/rails/NodeJSserver/server.js
Eu posso executar este arquivo muito bem por si só. Mas quando tento executá-lo como parte do serviço, percebo que meu servidor nodeJS não foi iniciado. Mesmo quando verifico "sudo systemctl --state=failed", não vejo nenhum erro ...
[rails@server ~]$ sudo systemctl enable NodeJSserver
[rails@server ~]$ sudo systemctl start NodeJSserver
[rails@server ~]$
[rails@server ~]$
[rails@server ~]$ forever list
info: No forever processes running
[rails@server ~]$
[rails@server ~]$
[rails@server ~]$ sudo systemctl --state=failed
UNIT LOAD ACTIVE SUB DESCRIPTION
● nginx.service loaded failed failed The nginx HTTP and reverse proxy server
● systemd-sysctl.service loaded failed failed Apply Kernel Variables
● systemd-vconsole-setup.service loaded failed failed Setup Virtual Console
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
3 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
Como descubro por que meu serviço falhou ao iniciar?
Seu serviço não foi
Type=
especificado na[Service]
seção, entãosystemd
suponha que você quis dizerType=simple
.Isso significa
systemd
que esperará que o processo iniciadoExecStart=
continue em execução enquanto o serviço estiver em execução. Mas parece que vocêstart.sh
executa apenas um comando e sai. Esse é oforever
comando :forever start
inicia o comando de destino como um daemon, ou seja, em segundo plano. Assim que oforever start
comando for concluído, o shell em execuçãostart.sh
será encerrado.Nesse ponto,
systemd
considera este serviço como com falha. Mas espere, o grupo de controle atribuído a esse serviço ainda tem um processo em execução. "Então", pensasystemd
, "não só falhou, mas também deixou uma bagunça depois de si. Não pode permitir isso." Como não háKillMode=
nemKillSignal=
especificado,systemd
continua com seus padrões e envia um SIGTERM para quaisquer processos restantes naquele grupo de controle e, se eles não pararem em tempo hábil, segue com um SIGKILL. Depois disso, seu processo NodeJS real estará morto, garantido.Como corrigi-lo
Como o comando com o qual você executa
ExecStart=
sairá assim que o servidor real for iniciado, você não poderá usar o padrãoType=simple
. Você deve especificar outro tipo de serviço.Você poderia usar o
Type=forking
. Com esse tipo,man systemd.service
recomenda o uso de umaPIDFile=
opção, portanto, se o seu servidor NodeJS criar um arquivo PID para si mesmo (ou você adicionar opções aoforever
comando para que ele crie um para ele), informesystemd
onde ele estará.Se
Type=forking
não funcionar para você, você pode especificarType=oneshot
comRemainAfterExit=yes
.Isso faz com que
systemd
apenas execute oExecStart=
comando ao iniciar seu serviço eExecStop=
ao interrompê-lo, e não se preocupe com mais nada.systemd
ainda se lembrará se o serviço foi definido pela última vez em um estado parado ou iniciado. Portanto, se você definir outro serviço para depender desse serviço e interromper seu serviço NodeJS manualmente, o outro serviço não será interrompido automaticamente e, sem dúvida, retornará erros quando não puder usar seu serviço NodeJS.A terceira opção é pular
forever
totalmente o comando e deixarsystemd
fazer o trabalho de reiniciar o processo NodeJS. Nesse caso, toda a suanodejs.service
unidade seria:Você pode adicionar outras opções.
Por exemplo, você pode especificar
RestartSec=5
uma suspensão de 5 segundos antes de tentar reiniciar o serviço se ele morrer inesperadamente, para evitar sobrecarregar os recursos do sistema com tentativas frequentes de reinicialização se o serviço continuar morrendo imediatamente após ser reiniciado por algum motivo. (ORestartSec=
valor padrão é 100 ms.)Ou se você deseja que o serviço seja reiniciado se retornar alguns valores de status de saída específicos, mas considera que falhou em outros, também existem opções para isso.