Comment savoir pourquoi mon service systemctl n'a pas démarré sur CentOS 7?


12

J'utilise CentOS 7. Comment savoir pourquoi un service ne démarre pas? J'ai créé ce service

[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

Le fichier pointe

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

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

Je peux exécuter ce fichier très bien par lui-même. Mais lorsque j'essaie de l'exécuter dans le cadre du service, je remarque que mon serveur nodeJS n'est pas démarré. Même lorsque je vérifie "sudo systemctl --state = failed", je ne vois aucune erreur ...

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

Comment savoir pourquoi mon service n'a pas pu démarrer?


journalctl -u nodejsdevrait vous donner un message d'erreur plus significatif.
Federico klez Culloca

Je reçois le message "Aucun fichier journal n'a été trouvé."
Dave

sudo journalctl devrait fonctionner. Toujours dans start.sh, voyez s'il redirige les fichiers journaux de sortie vers un autre emplacement.
rogerdpack

Réponses:


13

Votre service n'a pas Type=spécifié dans la [Service]section, systemdsuppose donc que vous vouliez dire Type=simple.

Cela signifie systemdque le processus démarré ExecStart=continuera de fonctionner tant que le service est en cours d'exécution. Mais il semble que votre start.shne lance qu'une seule commande, puis se termine. C'est la forevercommande : forever startdémarre la commande cible en tant que démon, ou en d'autres termes, en arrière-plan. Dès que la forever startcommande est terminée, le shell en cours d'exécution start.shse termine .

À ce stade, systemdconsidère que ce service a échoué. Mais attendez, le groupe de contrôle affecté à ce service a toujours un processus en cours. "Donc," pense-t-il systemd, "non seulement il a échoué, mais il a également laissé un gâchis après lui-même. Ça ne peut pas avoir ça." Puisqu'il n'y a aucun KillMode=ni KillSignal=spécifié, systemdcontinue avec ses valeurs par défaut et envoie un SIGTERM pour tous les processus restants dans ce groupe de contrôle, et s'ils ne s'arrêtent pas en temps opportun, suit avec un SIGKILL. Après cela, votre processus NodeJS réel sera mort, garanti.

Comment le réparer

Étant donné que la commande que vous exécutez ExecStart=se termine dès que le serveur réel est démarré, vous ne pouvez pas utiliser la valeur par défaut Type=simple. Vous devez spécifier un autre type de service.

Vous pouvez utiliser le Type=forking. Avec ce type, man systemd.servicerecommande d'utiliser une PIDFile=option, donc si votre serveur NodeJS crée un fichier PID pour lui-même (ou si vous ajoutez des options à la forevercommande pour en créer un), vous devez systemdindiquer où il se trouvera.

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

Si Type=forkingcela ne fonctionne pas pour vous, vous pouvez spécifier Type=oneshotavec RemainAfterExit=yes.

Cela fait systemdsimplement exécuter la ExecStart=commande au démarrage de votre service et ExecStop=à son arrêt, sans vous soucier d'autre chose.

systemdse souviendra toujours si le service a été défini pour la dernière fois à l'état arrêté ou démarré. Donc, si vous définissez un autre service pour dépendre de ce service, puis arrêtez votre service NodeJS manuellement, l'autre service ne s'arrêtera pas automatiquement et renverra sans aucun doute des erreurs lorsqu'il ne pourra pas utiliser votre service NodeJS.


La troisième option consiste à ignorer forevercomplètement la commande et à laisser systemdle travail de redémarrage du processus NodeJS. Dans ce cas, votre nodejs.serviceunité entière serait:

[Unit]
Description=nodejs server

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

[Install]
WantedBy=multi-user.target

Vous pouvez ajouter d'autres options.

Par exemple, vous pouvez spécifier RestartSec=5de spécifier un sommeil de 5 secondes avant de tenter de redémarrer le service s'il meurt de façon inattendue, pour éviter de monopoliser les ressources système par de fréquentes tentatives de redémarrage si votre service continue de mourir immédiatement après avoir été redémarré pour une raison quelconque. (La RestartSec=valeur par défaut est 100 ms.)

Ou si vous souhaitez que le service soit redémarré s'il renvoie des valeurs de statut de sortie spécifiques, mais que vous pensez qu'il a échoué sur d'autres, il existe également des options pour cela.


J'avais un service qui ne s'arrêtait pas et ne démarrerait pas correctement (il démarre, mais le processus systemctl ne se termine jamais). Je veux juste ajouter que dans mon cas, tout ce que j'avais à faire était d'ajouter Restart=alwaysà mon fichier de configuration .service.
Andy Forceno
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.