我有一项服务,我想通过 systemd 来管理——我们称之为foo
。我写了单元文件,它们工作得很好。因此,如果我运行systemctl start foo
,服务会正确启动,并且我可以通过systemctl status foo
.
但是,外部程序也可以启动该服务,并且它不使用 systemd 来启动该服务。因此,该服务可以运行,但由于它不是通过 systemd 启动的,因此 systemd 不知道它。在这种情况下,systemctl status foo
报告服务失败,即使它运行正常。
有没有办法让 systemd '继承'或'采用'这个服务,所以systemctl status foo
正确地报告服务正在运行,即使 systemd 没有启动它?使用 SysV,我会编写一个小的“状态”脚本,所以我可以/etc/init.d/foo status
,但这似乎不适合 systemd 模型。
需要明确的是,当外部程序启动服务时,服务的进程仍然是 PID 1/systemd 的子进程。但是,systemd 不会将它们识别为 service 的一部分foo
,因为 systemd 没有启动并注册它们。
具体技术有:
- Oracle WebLogic(服务是托管 WebLogic 实例)
- Oracle NodeManager(这是也可能启动服务的外部程序)
- 系统 219
不会。就 systemd 而言,该进程将在不同的上下文中运行。
事实上,这也是应该避免激活桌面总线服务的原因之一。就 systemd 而言,由 Desktop Bus 代理直接产生的服务进程是其服务的一部分。
可以在具有适当权限的控制组之间移动进程。但这只是工作的一半,另一半是让 systemd 相信它没有启动一个单元并重写其内部数据结构的必要部分,并没有提供。
这不仅不是 systemd 的模型,也不是大多数服务管理子系统的模型。
顺便说一句,太多人对甲骨文软件的“还不错”的服务单元实际上并不在恐怖屋领域。
进一步阅读
简而言之,没有办法让 systemd 考虑启动服务,除非它是由 systemd 本身启动的。systemd 的主要观点之一是管理服务的一致性,并且以不同的方式启动服务与该想法背道而驰。
现在,systemd确实提供了管理从外部启动的进程,这似乎有点适合您描述的情况。这实际上是一种单独的单元,一个范围单元。
使用范围单元仍然需要您的外部系统与 systemd 交互,因为范围单元只能通过对 systemd 的 D-Bus 请求启动,其中传递了一个 PID,该 PID 用作范围中的初始进程。此外,当一个作用域单元启动时,systemd 仍然希望自己创建 cgroups(然后它将传递的 PID 移动到创建的 cgroups 中。)因此,如果它希望 systemd 管理这些新进程,这需要应用程序创建新进程的支持作为范围。
简而言之,避免使用两种不同的方式来启动服务。如果您需要使用第三方服务管理器,请仅使用它。
如果您要解决的问题是在启动期间启动服务,那么:
检查您的第三方管理器(在您的情况下为 Oracle NodeManager)是否支持在启动期间配置服务。由于它正在管理服务,它也应该在启动期间管理服务。
如果您涉及 systemd,则使用一个简单的
oneshot
服务单元,该单元只需请求第三方管理器启动服务。这意味着通过某种 API 或 RPC(可能通过 HTTP)联系第三方管理器(在您的情况下为 Oracle NodeManager),并告诉它启动服务。如果您使用 systemd
oneshot
启动,请适当地命名您的单元(如“start-foo”或“initial-foo”或“foo-startup”)以明确它不会保持“up”,并保持RemainAfterExit=
为no
(默认值)因此检查该单元的状态只会说它已成功完成,因此它反映了在第三方管理器下运行的服务的状态没有混淆。