我如何弄清楚为什么我的systemctl服务没有在CentOS 7上启动?


12

我正在使用CentOS7。如何弄清为什么服务无法启动?我已经创建了这项服务

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

我如何找出为什么我的服务无法启动?


journalctl -u nodejs应该会给您更有意义的错误消息。
Federico klez Culloca

我收到消息“找不到日志文件”。
戴夫

sudo journalctl应该可以工作。同样在start.sh中,查看是否将输出日志文件重定向到其他地方。
rogerdpack

Answers:


13

您的服务未Type=在此[Service]部分中指定,因此systemd假设您的意思是Type=simple

这意味着只要服务正在运行systemd,开始的进程就会ExecStart=一直运行。但是看来您start.sh只运行一个命令然后退出。也就是说forever命令forever start启动目标命令作为守护程序,或者换句话说,在背景中。只要forever start命令完成后,shell中运行start.sh将退出。

那时,systemd认为此服务失败。但是,等等,分配给该服务的控制组中仍然有一个正在运行的进程。“所以,”他认为systemd,“它不仅失败了,而且还留下了一个烂摊子。不能那样做。” 由于没有KillMode=也没有KillSignal=指定,因此systemd继续使用其默认值,并为该控制组中的所有其余进程发送SIGTERM,如果没有及时停止,请执行SIGKILL。之后,您的实际NodeJS进程将被终止,这是有保证的。

如何修复

由于您运行的命令ExecStart=将在实际服务器启动后立即退出,因此您不能使用default Type=simple。您必须指定其他服务类型。

您可以使用Type=forking。对于这种类型,man systemd.service建议使用一个PIDFile=选项,因此,如果您的NodeJS服务器为其自身创建一个PID文件(或者您在该forever命令中添加选项以使其为其创建一个PID文件),则应systemd告知其位置。

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

如果Type=forking不为你工作,那么你可以指定Type=oneshot使用RemainAfterExit=yes

这样systemd就可以ExecStart=在启动服务和ExecStop=停止服务时运行命令,而无需关心其他任何事情。

systemd仍然会记住该服务是最后一次设置为停止还是启动状态。因此,如果您将另一个服务设置为依赖于该服务,然后手动停止您的NodeJS服务,则该其他服务将不会自动停止,并且当它不能使用NodeJS服务时无疑会返回错误。


第三种选择是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毫秒。)

或者,如果您希望服务在返回某些特定的退出状态值时重新启动,但又认为该服务在其他退出状态上失败,则也可以使用该选项。


我的服务没有停止,也无法正常启动(它启动了,但是systemctl进程从不退出)。在我的情况下只是想添加,我要做的就是添加Restart=always到我的.service配置文件中。
Andy Forceno,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.