Come faccio a capire perché il mio servizio systemctl non è stato avviato su CentOS 7?


12

Sto usando CentOS 7. Come posso capire perché un servizio non si avvia? Ho creato questo servizio

[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

Il file punta a questo

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

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

Posso eseguire questo file bene da solo. Ma quando provo ad eseguirlo come parte del servizio, noto che il mio server nodeJS non è avviato. Anche quando controllo "sudo systemctl --state = failed", non vedo alcun errore ...

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

Come faccio a capire perché il mio servizio non è stato avviato?


journalctl -u nodejsdovrebbe darti un messaggio di errore più significativo.
Federico Klez Culloca,

Viene visualizzato il messaggio "Nessun file journal trovato."
Dave,

sudo journalctl dovrebbe funzionare. Anche all'interno di start.sh verifica se sta reindirizzando i file di registro di output da qualche altra parte.
rogerdpack,

Risposte:


13

Il servizio non è stato Type=specificato nella [Service]sezione, quindi systemdpresuppone che tu intendessi Type=simple.

Ciò significa che systemdsi aspetterà che il processo avviato ExecStart=continui finché il servizio è in esecuzione. Ma sembra che tu start.shesegua solo un comando e poi esca. Questo è il forevercomando : forever startavvia il comando target come demone o, in altre parole, in background. Non appena il forever startcomando viene completato, la shell in esecuzione start.shverrà chiusa.

A quel punto, systemdconsidera questo servizio come fallito. Ma aspetta, il gruppo di controllo assegnato a quel servizio ha ancora un processo in esecuzione in esso. "Quindi", pensa systemd, "non solo ha fallito, ma ha anche lasciato un casino dopo se stesso. Non può averlo." Poiché non è specificato KillMode=KillSignal=specificato, systemdcontinua con i valori predefiniti e invia un SIGTERM per tutti i processi rimanenti in quel gruppo di controllo e, se non si arrestano in modo tempestivo, fa seguito a un SIGKILL. Successivamente, il processo NodeJS effettivo sarà interrotto, garantito.

Come sistemarlo

Poiché il comando con cui ExecStart=eseguirai verrà chiuso non appena viene avviato il server effettivo, non è possibile utilizzare l'impostazione predefinita Type=simple. È necessario specificare un altro tipo di servizio.

Puoi usare il Type=forking. Con questo tipo, man systemd.serviceconsiglia di utilizzare PIDFile=un'opzione, quindi se il tuo server NodeJS crea un file PID per se stesso (o aggiungi opzioni al forevercomando per farne crearne uno), dovresti far systemdsapere dove sarà.

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

Se Type=forkingnon funziona per te, è possibile specificare Type=oneshotcon RemainAfterExit=yes.

Ciò fa systemdsemplicemente eseguire il ExecStart=comando quando si avvia il servizio e ExecStop=quando lo si interrompe, e non importa nulla.

systemdricorderà comunque se il servizio è stato impostato per l'ultima volta in uno stato arrestato o avviato, comunque. Quindi, se imposti un altro servizio in modo che dipenda da questo servizio, quindi interrompi manualmente il servizio NodeJS, l'altro servizio non si arresterà automaticamente e senza dubbio restituirà errori quando non può utilizzare il servizio NodeJS.


La terza opzione è saltare completamente il forevercomando e lasciare che systemdfaccia il lavoro di riavvio del processo NodeJS. In tal caso, l'intera nodejs.serviceunità sarebbe:

[Unit]
Description=nodejs server

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

[Install]
WantedBy=multi-user.target

Potresti aggiungere altre opzioni.

Ad esempio, è possibile specificare RestartSec=5di specificare una sospensione di 5 secondi prima di tentare di riavviare il servizio se si interrompe in modo imprevisto, per evitare le risorse del sistema di hogging con frequenti tentativi di riavvio se il servizio continua a morire immediatamente dopo il riavvio per qualche motivo. (Il RestartSec=valore predefinito è 100 ms.)

Oppure, se si desidera riavviare il servizio se restituisce alcuni valori di stato di uscita specifici, ma si considera che non è riuscito su altri, ci sono opzioni anche per quello.


Avevo un servizio che non si arrestava e che non si avviava correttamente (si avvia, ma il processo systemctl non termina mai). Voglio solo aggiungere che nel mio caso, tutto quello che dovevo fare era aggiungere Restart=alwaysal mio file di configurazione .service.
Andy Forceno,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.