我有一个简单的systemd服务单元来启动我的Node.JS Web服务器,出于某种原因, Restart=on-failure不起作用并重新启动进程。
这是我的服务单元文件(删除了专有名称):
[Unit] Description=Node.JS web server After=network.target [Service] User=villa Environment=NODE_PATH=. WorkingDirectory=/path/to/server/code PermissionsStartOnly=true ExecStart=/usr/local/bin/node server.js ExecStop=/bin/killall node Restart=on-failure RestartSec=1 [Install] WantedBy=multi-user.target
接下来,我做一个daemon-reload ,然后restart这个进程,并用像这样的SIGKILL杀死它:
[root@localhost ~]# ps -ef | grep node villa 24783 1 17 10:54 ? 00:00:00 /usr/local/bin/node server.js root 25172 26051 0 10:54 pts/1 00:00:00 grep --color=auto node [root@localhost ~]# kill -9 24783 [root@localhost ~]# sleep 2 [root@localhost ~]# ps -ef | grep node root 29462 26051 0 10:55 pts/1 00:00:00 grep --color=auto node
正如您所看到的,即使在等待比RestartSec设置更长的时间后,进程也不会重新启动。
杀死上面这个过程之后,这就是现状:
[root@localhost ~]# systemctl -l status webserver.service ● webserver.service - Node.JS web server Loaded: loaded (/etc/systemd/system/webserver.service; enabled; vendor preset: disabled) Active: failed (Result: exit-code) since Wed 2017-05-03 10:54:53 EDT; 7min ago Process: 27843 ExecStop=/bin/killall node (code=exited, status=1/FAILURE) Process: 24783 ExecStart=/usr/local/bin/node server.js (code=killed, signal=KILL) Main PID: 24783 (code=killed, signal=KILL) May 03 10:54:31 localhost.localdomain node[24783]: <...web server's standard output, nothing abnormal at all...> May 03 10:54:53 localhost.localdomain systemd[1]: webserver.service: main process exited, code=killed, status=9/KILL May 03 10:54:53 localhost.localdomain systemd[1]: webserver.service: control process exited, code=exited status=1 May 03 10:54:53 localhost.localdomain systemd[1]: Unit webserver.service entered failed state. May 03 10:54:53 localhost.localdomain systemd[1]: webserver.service failed.
奇怪的是,如果我使用这个完全相同的服务单元文件,但使用命令/usr/bin/sleep 1000而不是node server.js , sleep过程将在我的kill -9之后正确地重新启动。 所以Node.JS肯定会有一些奇怪的事情发生。
任何想法,为什么我的节点进程不开始备份?
事实certificate,我的systemd服务单元文件一直是正确的(删除了马克发布的ExecStop=行,这使得我的文件更加正确)。 我的问题是我的服务单元文件位于/usr/lib/systemd/system ,不幸的是,另一个开发者没有告诉我,把同一个文件放在/etc/systemd/system ,而不是Restart=行。
根据systemd.unit(5) ( man systemd.unit ):
单元文件是从编译过程中确定的一组path加载的,如下表所述。 在前面列出的目录中find的单元文件会覆盖列表中较低的目录中具有相同名称的文件。
Table 1. Load path when running in system mode (--system). ┌────────────────────────┬─────────────────────────────┐ │Path │ Description │ ├────────────────────────┼─────────────────────────────┤ │/etc/systemd/system │ Local configuration │ ├────────────────────────┼─────────────────────────────┤ │/run/systemd/system │ Runtime units │ ├────────────────────────┼─────────────────────────────┤ │/usr/lib/systemd/system │ Units of installed packages │ └────────────────────────┴─────────────────────────────┘
所以,简而言之,systemd在/etc/systemd/system看到没有Restart=行的文件,它在/usr/lib/systemd/system看到我的更新文件,线。 我只需要删除过时的文件,我的问题就解决了。
我读取日志的方式可能会因为ExecStop=/bin/killall node而死亡,该ExecStop=/bin/killall node被列为退出状态为“1 / FAILURE”。
看来这个killall命令是以PermissionsStartOnly=true作为根目录运行的。 ExecStop命令似乎也不必要。 这是危险的,因为它可以杀死与本单元无关的节点进程。 以root身份运行,可能会产生意想不到的后果。
这也是没有必要的,因为systemd会停止你的Node应用程序。 默认情况下,它会首先发送一个SIGTERM进程。 那么如果它没有回应,那么SIGKILL将会发布。
尝试删除您的ExecStop=行。