¿Cómo puedo averiguar por qué mi servicio systemctl no se inició en CentOS 7?

12

Estoy usando CentOS 7. ¿Cómo puedo averiguar por qué un servicio no se inicia? He creado este servicio

[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

El archivo apunta a esto

[rails@server ~]$ cat /home/rails/NodeJSserver/start.sh
#!/bin/bash

forever start /home/rails/NodeJSserver/server.js

Puedo ejecutar este archivo muy bien por sí mismo. Pero cuando intento ejecutarlo como parte del servicio, noto que mi servidor nodeJS no está iniciado. Incluso cuando verifico "sudo systemctl --state = falló", no veo ningún error ...

[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'.

¿Cómo puedo averiguar por qué mi servicio no pudo iniciarse?

Dave
fuente
journalctl -u nodejsdebería darte un mensaje de error más significativo.
Federico klez Culloca
Recibo el mensaje "No se encontraron archivos de diario".
Dave
sudo journalctl debería funcionar. También dentro de start.sh, vea si está redirigiendo los archivos de registro de salida a otro lugar.
rogerdpack

Respuestas:

13

Su servicio no se ha Type=especificado en la [Service]sección, por lo que se systemdsupone que quiso decir Type=simple.

Eso significa systemdque esperará que el proceso que se inició ExecStart=continúe ejecutándose mientras se ejecute el servicio. Pero parece que start.shsolo ejecuta un comando y luego sale. Ese es el forevercomando : forever startinicia el comando de destino como un demonio, o en otras palabras, en segundo plano. Tan pronto como se forever startcomplete el comando, se start.shcerrará el shell en ejecución .

En ese momento, systemdconsidera este servicio como fallido. Pero espere, el grupo de control asignado para ese servicio todavía tiene un proceso en ejecución. "Entonces", piensa systemd, "no solo falló, sino que también dejó un desastre tras sí mismo. No puedo soportarlo". Como no hay KillMode=ni KillSignal=especificado, systemdcontinúa con sus valores predeterminados y envía un SIGTERM para los procesos restantes en ese grupo de control, y si no se detienen de manera oportuna, realiza un seguimiento con un SIGKILL. Después de eso, su proceso real de NodeJS estará muerto, garantizado.

Como arreglarlo

Dado que el comando que ejecuta se ExecStart=cerrará tan pronto como se inicie el servidor real, no puede usar el predeterminado Type=simple. Debe especificar otro tipo de servicio.

Podrías usar el Type=forking. Con este tipo, man systemd.servicerecomienda usar una PIDFile=opción, por lo que si su servidor NodeJS crea un archivo PID para sí mismo (o agrega opciones al forevercomando para que cree uno para él), debe informar systemddónde estará.

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

Si Type=forkingno funciona para usted, puede especificar Type=oneshotcon RemainAfterExit=yes.

Eso hace que systemdsimplemente ejecute el ExecStart=comando al iniciar su servicio y ExecStop=al detenerlo, y no le importe nada más.

systemdaún así recordará si el servicio se configuró por última vez en estado detenido o iniciado. Entonces, si configura otro servicio para que dependa de este servicio, y luego detenga su servicio NodeJS manualmente, el otro servicio no se detendrá automáticamente y sin duda devolverá errores cuando no pueda usar su servicio NodeJS.


La tercera opción es omitir el forevercomando por completo y dejar de systemdhacer el trabajo de reiniciar el proceso NodeJS. En ese caso, toda su nodejs.serviceunidad sería:

[Unit]
Description=nodejs server

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

[Install]
WantedBy=multi-user.target

Podrías agregar otras opciones.

Por ejemplo, podría especificar RestartSec=5especificar un modo de suspensión de 5 segundos antes de intentar reiniciar el servicio si se muere inesperadamente, para evitar acaparar los recursos del sistema mediante intentos frecuentes de reinicio si su servicio sigue muriendo inmediatamente después de ser reiniciado por alguna razón. (El RestartSec=valor predeterminado es 100 ms.)

O si desea que el servicio se reinicie si devuelve algunos valores de estado de salida específicos, pero considera que falló en otros, también hay opciones para eso.

telcoM
fuente
Tenía un servicio que no se detenía y no se iniciaba correctamente (se inicia, pero el proceso systemctl nunca se cierra). Solo quiero agregar eso en mi caso, todo lo que necesitaba hacer era agregarlo Restart=alwaysa mi archivo de configuración .service.
Andy Forceno