为什么 systemd 不知道服务是否失败?

为什么 systemd 不知道服务是否失败?

我正在尝试在 Ubuntu 18.04 上配置 spring-boot 应用程序(由其他人开发 - 我不是 java 程序员)。开发人员之前添加了符号链接来/etc/init.d启用该服务 - 它在启动时启动良好。但是,如果该服务随后失败,systemd 仍会报告它正在运行:

[email protected]:/var/log/apps# systemctl status crm-service
● crm-service.service - LSB: crm-service
   Loaded: loaded (/etc/init.d/crm-service; generated)
   Active: active (exited) since Wed 2020-04-15 12:27:15 BST; 3h 56min ago
     Docs: man:systemd-sysv-generator(8)
  Process: 8656 ExecStop=/etc/init.d/crm-service stop (code=exited, status=0/SUCCESS)
  Process: 8703 ExecStart=/etc/init.d/crm-service start (code=exited, status=0/SUCCESS)

Apr 15 12:27:15 example.com systemd[1]: Starting LSB: crm-service...
Apr 15 12:27:15 example.com crm-service[8703]: /var/services/crm-service.conf: line 1: -Xms96M: command not found
Apr 15 12:27:15 example.com crm-service[8703]: Started [8747]
Apr 15 12:27:15 example.com systemd[1]: Started LSB: crm-service.

当我看到相同的 systemd 单元文件对于互联网上发布的 springboot,我没有看到任何可能解决此问题的内容。

  1. 如何让 systemd 查看服务的真实状态? (它将打开一个侦听套接字,但在随机的高端口上)
  2. 有没有办法让 systemd 尝试一下轻轻地重新启动它知道失败的服务?

答案1

Systemd 有很多批评者,其中很多都还不错,但事实并非如此。Systemd 可以跟踪从启动脚本分叉(或克隆)的所有进程和线程,如果没有留下任何进程和线程,则认为服务已死亡。

我看到的第一个问题是:systemd 不使用启动/停止脚本/etc/init.d,它只是一个兼容性插件。相反,systemd 使用单元文件,即其所有服务的配置文件。

systemd sysv init compat 模块有效地为/etc/init.d.这并不总是可以的,因为初始化脚本缺少所需的信息(或者不可能从它们中提取信息)。

该 compat 模块的工作方式是,如果退出代码非零,则 systemd 认为 init 脚本失败,因此服务无法工作。零退出代码意味着成功执行。如果 init 脚本有错误并且即使失败也给出零退出代码,它会欺骗 systemd。

初始化脚本错误的最可能原因是它在后台启动进程,然后总是以零退出。我对大多数由自定义提供程序编写的初始化脚本的共同经验是……也许它们中的大多数都有很大的改进空间。不要相信他们,看看他们做了什么并修复它们。对于你的情况,最好是检查一下,

  • 它如何启动你的java应用程序
  • 从哪里开始
  • 由哪个用户启动

并使用单元文件重现相同的功能。

无法从 systemd 自动重新启动 initscripts,但可以从单元文件中自动重新启动。

请注意,如果 Java 程序随机崩溃,这也是一个严重的问题。所有健全的 java 框架都会正确处理自己的致命错误(它们捕获所有异常,记录并继续)。

init 脚本中另一个很可能的错误是它找不到您的 JVM(最有可能是:/usr/bin/java),因此它用空字符串替换它,导致它尝试将 JVM 标志作为 shell 命令启动。显然-Xms96M您的系统中没有命令,但/usr/bin/java -Xms96M ...可以使用。

Spring Boot 应用程序的示例单元文件:

[Unit]
Description=Crm Spring Boot App Example
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/java -Xms96M ...other flags... your.spring.boot.jar
User=exampleuser
Group=examplegroup
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=exampleapp
WorkingDirectory=/path/to/app/home

[Install]
WantedBy=multi-user.target
Alias=exampleapp.service

该单元文件还将 Java 进程的标准输出和错误重定向到系统日志中。

要自动重新启动应用程序,请插入

RestartSec=5s
Restart=on-failure

进入该[Service]部分。

有一个 systemd 教程GoLinuxCloud.com

相关内容