Estou usando o CentOS 7. Como descobrir 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 este
[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 eu checo "sudo systemctl --state = falhou", não vejo erros ...
[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 faço para descobrir por que meu serviço falhou ao iniciar?
journalctl -u nodejs
deve fornecer uma mensagem de erro mais significativa.Respostas:
Seu serviço não está
Type=
especificado na[Service]
seção, portanto,systemd
assume o que você quis dizerType=simple
.Isso significa
systemd
que o processo iniciadoExecStart=
continuará 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 target como um daemon, ou em outras palavras, 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 com falha. Mas espere, o grupo de controle designado para esse serviço ainda possui um processo em execução. "Então", pensasystemd
, "não apenas falhou, mas também deixou uma bagunça em si. Não pode ter isso." Como não háKillMode=
nemKillSignal=
especificado,systemd
continua com seus padrões e envia um SIGTERM para todos os processos restantes nesse grupo de controle e, se eles não param em tempo hábil, segue com um SIGKILL. Depois disso, seu processo real do NodeJS 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-se o uso de umaPIDFile=
opção; portanto, se o servidor NodeJS criar um arquivo PID para si próprio (ou você adicionar opções aoforever
comando para criar um para ele), informesystemd
onde será.Se
Type=forking
não funcionar para você, você pode especificarType=oneshot
comRemainAfterExit=yes
.Isso faz
systemd
apenas executar oExecStart=
comando ao iniciar o serviço eExecStop=
ao interrompê-lo, e não se importa com mais nada.systemd
ainda lembrará se o serviço foi definido pela última vez em um estado parado ou iniciado. Portanto, se você configurar outro serviço para depender desse serviço e parar o serviço NodeJS manualmente, o outro serviço não será interrompido automaticamente e sem dúvida retornará erros quando não puder usar o serviço NodeJS.A terceira opção é ignorar o
forever
comando completamente e deixarsystemd
o trabalho de reiniciar o processo do NodeJS. Nesse caso, suanodejs.service
unidade inteira seria:Você pode adicionar outras opções.
Por exemplo, você pode especificar
RestartSec=5
para especificar um sono de 5 segundos antes de tentar reiniciar o serviço se ele morrer inesperadamente, para evitar sobrecarregar os recursos do sistema por 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 considerar que falhou em outros, também existem opções para isso.
fonte
Restart=always
ao meu arquivo de configuração .service.