web-dev-qa-db-ja.com

CentOS 7でsystemctlサービスが開始されなかった理由を知るにはどうすればよいですか?

CentOS 7を使用しています。サービスの開始に失敗する理由を知るにはどうすればよいですか?このサービスを作成しました

[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

ファイルはこれを指しています

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

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

このファイルだけで問題なく実行できます。しかし、サービスの一部として実行しようとすると、nodeJSサーバーが起動していないことがわかります。 「Sudo systemctl --state = failed」をチェックしてもエラーが表示されません...

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

サービスの開始に失敗した理由を知るにはどうすればよいですか?

12
Dave

サービスのType=[Service]セクションで指定されていないため、systemdType=simpleを意味していると想定します。

つまり、systemdは、サービスが実行されている限り、ExecStart=で開始されたプロセスが実行を継続することを期待します。しかし、start.shは1つのコマンドしか実行せずに終了するようです。つまり the forever commandforever startはターゲットコマンドをデーモンとして、つまりバックグラウンドで開始します。 forever startコマンドが完了するとすぐに、start.shを実行しているシェルが終了します。

その時点で、systemdはこのサービスが失敗したと見なします。ただし、そのサービスに割り当てられたコントロールグループには、まだ実行中のプロセスがあります。 「それで」とsystemdは考えます、「失敗しただけでなく、それ自体が混乱を残しました。それはあり得ません。」 KillMode=KillSignal=も指定されていないため、systemdはデフォルトで続行し、そのコントロールグループ内の残りのプロセスにSIGTERMを送信します。タイムリーに、SIGKILLをフォローアップします。その後、実際のNodeJSプロセスは保証されます。

それを修正する方法

ExecStart=で実行するコマンドは、実際のサーバーが起動するとすぐに終了するため、デフォルトのType=simpleを使用することはできません。別のサービスタイプを指定する必要があります。

Type=forkingを使用できます。このタイプでは、man systemd.servicePIDFile=オプションの使用をお勧めします。そのため、NodeJSサーバーがそれ自体のPIDファイルを作成する場合(またはforeverコマンドにオプションを追加して、それ)、それがどこにあるかをsystemdに知らせる必要があります。

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

Type=forkingが機能しない場合は、Type=oneshotRemainAfterExit=yesと一緒に指定できます。

これにより、サービスを開始するときにsystemdを実行するだけでExecStart=コマンドを実行し、サービスを停止するときにはExecStop=を実行するだけで済みます。

ただし、systemdは、サービスが最後に停止状態または開始状態に設定されたかどうかを記憶します。したがって、このサービスに依存するように別のサービスを設定し、NodeJSサービスを手動で停止した場合、他のサービスは自動的に停止せず、NodeJSサービスを使用できないときに間違いなくエラーを返します。


3番目のオプションは、foreverコマンドを完全にスキップして、systemdにNodeJSプロセスを再起動するジョブを実行させることです。その場合、nodejs.serviceユニット全体は次のようになります。

[Unit]
Description=nodejs server

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

[Install]
WantedBy=multi-user.target

他のオプションを追加できます。

たとえば、RestartSec=5を指定して、サービスが予期せず停止した場合にサービスの再起動を試みる前に5秒のスリープを指定し、何らかの理由でサービスが再起動した直後にサービスが停止し続ける場合に頻繁な再起動の試行によってシステムリソースが占有されるのを回避できます。 。 (デフォルトのRestartSec=値は100ミリ秒です。)

または、サービスが特定の終了ステータス値を返したときにサービスを再起動したいが、他のサービスでは失敗したと考える場合、そのためのオプションもあります。

13
telcoM