Como faço para descobrir por que meu serviço systemctl não foi iniciado no CentOS 7?

12

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?

Dave
fonte
journalctl -u nodejsdeve fornecer uma mensagem de erro mais significativa.
Federico klez Culloca
Recebo a mensagem "Nenhum arquivo de diário foi encontrado".
Dave
O sudo journalctl deve funcionar. Também em start.sh, veja se está redirecionando os arquivos de log de saída para outro lugar.
Rogerdpack 9/07/19

Respostas:

13

Seu serviço não está Type=especificado na [Service]seção, portanto, systemdassume o que você quis dizer Type=simple.

Isso significa systemdque o processo iniciado ExecStart=continuará em execução enquanto o serviço estiver em execução. Mas parece que você start.shexecuta apenas um comando e sai. Esse é o forevercomando : forever startinicia o comando target como um daemon, ou em outras palavras, em segundo plano. Assim que o forever startcomando for concluído, o shell em execução start.shserá encerrado.

Nesse ponto, systemdconsidera 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", pensa systemd, "não apenas falhou, mas também deixou uma bagunça em si. Não pode ter isso." Como não há KillMode=nem KillSignal=especificado, systemdcontinua 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ão Type=simple. Você deve especificar outro tipo de serviço.

Você poderia usar o Type=forking. Com esse tipo, man systemd.servicerecomenda-se o uso de uma PIDFile=opção; portanto, se o servidor NodeJS criar um arquivo PID para si próprio (ou você adicionar opções ao forevercomando para criar um para ele), informe systemdonde será.

[Service]
Type=forking
PIDFile=/absolute/path/to/nodejs.pid
User=rails
... <the rest as before>

Se Type=forkingnão funcionar para você, você pode especificar Type=oneshotcom RemainAfterExit=yes.

Isso faz systemdapenas executar o ExecStart=comando ao iniciar o serviço e ExecStop=ao interrompê-lo, e não se importa com mais nada.

systemdainda 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 forevercomando completamente e deixar systemdo trabalho de reiniciar o processo do NodeJS. Nesse caso, sua nodejs.serviceunidade inteira seria:

[Unit]
Description=nodejs server

[Service]
User=rails
Group=rails
ExecStart=/home/rails/NodeJSserver/server.js
Restart=always

[Install]
WantedBy=multi-user.target

Você pode adicionar outras opções.

Por exemplo, você pode especificar RestartSec=5para 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. (O RestartSec=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.

telcoM
fonte
Eu tinha um serviço que não estava parando e não seria iniciado corretamente (ele inicia, mas o processo systemctl nunca sai). Só quero adicionar isso no meu caso, tudo o que eu precisava fazer era adicionar Restart=alwaysao meu arquivo de configuração .service.
Andy Forceno 04/04/19