我正在尝试在 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,我没有看到任何可能解决此问题的内容。
- 如何让 systemd 查看服务的真实状态? (它将打开一个侦听套接字,但在随机的高端口上)
- 有没有办法让 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。