我有一个基于systemd
分叉服务的启动脚本(我们称之为)foo
YAJSW(另一个 Java 服务包装器)。文件的相关部分.service
如下所示:
ExecStart=/opt/foo/startup.sh
ExecStop=/opt/foo/shutdown.sh
Restart=always
Type=forking
PIDFile=/opt/foo/wrapper.pid
该startup.sh
脚本负责启动 YAJSW 包装器。设置 YAJSW 配置文件,以便在启动期间将其 PID 写入文件:
wrapper.pidfile = /opt/foo/wrapper.pid
这样,如果包装器进程终止(出于任何原因),systemd 应该将其启动,这是所需的行为。我已经验证此配置工作正常,但在journalctl中显示了一条奇怪的行:
foo.service: PID file /opt/foo/wrapper.pid not readable (yet?) after start: No such file or directory
奇怪的是,systemctl status foo 正确显示了主 PID:
foo.service
...
Main PID: 12313 (java)
我是否做错了什么,或者这是软件组件之一的错误?我运行的是 Ubuntu 16.04.3 LTS,内核版本 4.4.0,systemd 版本 229.4。任何帮助将不胜感激。
答案1
分叉服务 [...] YAJSW(又一个 Java 服务包装器)[...]
ExecStart=/opt/foo/startup.sh
[...]ExecStop=/opt/foo/shutdown.sh
[...] PID 被写入文件 [...]
这类东西在 Java 中很常见,而且实际上似乎在一般的 Oracle 系统中也很常见;但也完全没有必要。您不需要用 shell 脚本或 Java 编写的 Poor Man 服务管理器在实际的服务管理器下运行。 PID 文件是一种完全危险且不稳定的机制。您不需要startup.sh
脚本shutdown.sh
,它们最终会将实际的服务流程推向流程树,从而没有好结果。您不需要额外的 YAJSW 配置文件。您不需要基于在内存中缓冲标准输出的复杂且特殊的日志记录机制。
您的服务进程应该由实际服务管理直接管理,并且不会使用 systemd 分叉就绪协议,因为几乎没有任何东西实际上使用它。不要使用包装 shell 脚本来运行 Poor Man 的服务管理器。不要使用 PID 文件。任何 shell 脚本包装器都应该链式加载,而不是 fork。你的配置文件是systemd服务单元文件,而不是一些其他配置文件。您的日志记录机制是服务管理附带的一种机制,它捕获标准输出和标准错误并将其数据写入文件。
进一步阅读
- 乔纳森·德博因·波拉德 (2015)。将 Apache Tomcat 包装在许多无意义的额外层中 systemd 恐怖屋。
- 乔纳森·德博因·波拉德 (2015)。 systemd 恐怖屋。经常给出的答案。
- 如何避免 /usr/bin/env 在 systemd 日志中被标记为可执行文件
- 使用 systemd 配置 java 守护进程
- https://unix.stackexchange.com/a/434726/5132
- 乔纳森·德博因·波拉德 (2016)。在本世纪不要使用
logrotate
or 。newsyslog
。经常给出的答案。
答案2
我不会说这是一个错误,而是一个复杂性问题。您当前拥有此链,只是为了启动和管理您的应用程序:
systemd -> startup.sh -> YAJSW -> actual app
我不知道startup.sh和YAJSW到底在做什么,但最好尝试简化管理:
systemd -> actual app
那么如果管理出现问题的话很多更容易推理发生的事情。
我建议通过最大限度地使用systemd
管理工具并最小化或消除脚本和 YAJSW 正在执行的操作来简化情况。