我有一个服务,我想通过 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
答案1
不会。就 systemd 而言,该进程将在不同的上下文中运行。
事实上,这是应避免桌面总线服务激活的原因之一。就 systemd 而言,由桌面总线代理直接生成的服务进程是其服务的一部分。
人们可以使用适当的权限在控制组之间移动进程。但这只是工作的一半,而另一半,即让 systemd 相信它在没有启动一个单元的情况下启动了一个单元,并重写其内部数据结构的必要部分,则没有提供。
这不仅不是 systemd 的模型,也不是大多数服务管理子系统的模型。
顺便说一句,太多人对 Oracle 软件的“还不错”服务单位实际上并不是这样,而是在恐怖之屋领土。
进一步阅读
- 如果守护进程是通过 systemctl 以外的机制启动的,则 systemctl 无法准确报告守护进程的状态
- 使用 systemd 配置 java 守护进程
- https://unix.stackexchange.com/a/437461/5132
- 乔纳森·德博因·波拉德 (2016)。避免桌面总线 (D-Bus) 总线激活 。吃点东西。软件。
- 乔纳森·德博因·波拉德 (2015)。 systemd 恐怖屋。经常给出的答案。
答案2
简而言之,除非服务是由 systemd 本身启动的,否则没有办法让 systemd 考虑启动该服务。 systemd 的要点之一是管理服务的一致性,而采用不同的方式来启动服务则违背了这一想法。
现在,系统做有一项规定可以管理外部启动的流程,这似乎有点适合您描述的情况。这实际上是一种单独的单位,一个范围单位。
使用作用域单元仍然需要外部系统与 systemd 交互,因为作用域单元只能通过对 systemd 的 D-Bus 请求来启动,其中传递 PID,用作作用域中的初始进程。此外,当启动作用域单元时,systemd 仍然希望自己创建 cgroup(然后它将传递的 PID 移动到创建的 cgroup 中)。因此,如果希望 systemd 管理这些进程,则需要创建新进程的应用程序的支持作为一个范围。
简而言之,避免使用两种不同的方式来启动服务。如果您需要使用第三方服务管理器,请仅使用它。
如果您要解决的问题是在启动过程中启动服务,那么:
检查您的第三方管理器(在您的情况下为 Oracle NodeManager)是否支持在启动期间配置服务。由于它管理服务,因此它也应该在启动期间管理服务。
如果您涉及 systemd,则使用一个简单的
oneshot
服务单元,只需请求第三方管理器启动服务即可。这意味着通过某种 API 或 RPC(可能通过 HTTP)联系第三方管理器(在您的例子中为 Oracle NodeManager),并告诉它启动服务。
如果您使用 systemdoneshot
进行启动,请适当地命名您的单元(例如“start-foo”或“initial-foo”或“foo-startup”)以明确它不会保持“启动”状态,并保持RemainAfterExit=
为no
(默认值),因此检查该单元的状态只会表明它已成功完成,因此不会混淆它反映了在第三方管理器下运行的服务的状态。