我们的应用程序使用 init.d 脚本来启动和停止应用程序作为服务。在 CentOS 7 下,/sbin/init
符号链接到 systemd,因此我可以使用以下任一方法启动我的应用程序:
service myapp start
或者
systemctl start myapp
我遇到的问题是,使用或stop
在服务上运行不会停止我的应用程序。的输出:service
systemctl
systemctl status
[root@nec04 ~]# systemctl status myapp
myapp.service - SYSV: Service script to start/stop my application
Loaded: loaded (/etc/rc.d/init.d/myapp)
Active: inactive (dead) since Mon 2015-10-05 15:17:41 CEST; 22h ago
Process: 31850 ExecStop=/etc/rc.d/init.d/myapp stop (code=exited, status=0/SUCCESS)
Process: 21054 ExecStart=/etc/rc.d/init.d/myapp start (code=exited, status=0/SUCCESS)
使用service
命令:
[root@nec04 ~]# service myapp status
Local database at :3307 is started
Watchdog is running
Application is running
为什么systemctl
认为我的应用程序没有运行?难道 systemctl 没有调用 stop 函数,因为它认为我的应用程序已经停止了?
答案1
我不知道输出service
,从未真正使用过该工具,但根据systemctl
应用程序确实已停止。这就是这Active: inactive (dead)
条线的意思。 (Loaded
仅意味着 systemd 已将单元文件加载到内存中;无论应用程序是否正在运行,这都应该始终如此。)
如果应用程序实际上仍然有一个进程在运行,则意味着停止功能无法正常工作。然而,这不应该发生;一旦systemctl
停止某些内容,它将(在超时后)使用 cgroup 强制终止该应用程序启动的所有进程。因此,除非您的进程以 root 身份运行并且故意脱离其 cgroup(一种极其病态的行为),否则 systemd 应该杀死它。不过,我不确定它如何与 sysVinit 仿真交互。
由于 systemd 使用其 sysVinit 模拟,将 init 脚本用作单元文件,因此整个问题变得复杂。重写为适当的单元文件可能会更好,如所述这里。我倾向于建议使用Type=simple
而不是,因为程序拥有switch 或等效项比与 dbus 对话Type=dbus
更常见,而且这也更容易添加到您可以控制的代码中。--no-daemon
答案2
为什么
systemctl
认为我的应用程序没有运行?
因为,正如汤姆·亨特所说,它没有运行。
难道是
systemctl
因为它认为我的应用程序已经停止而没有调用停止函数?
不,非常清楚做过调用 stop 函数,并将其作为进程#31850 运行。
这里有两种可能性,都不是 systemd 问题:
- 在某些时候,您直接启动服务程序,而不是作为 systemd 服务。这就是仍在运行的内容。当然systemd不会知道这一点。
status
您的脚本的功能有init.d
问题。这并不是init.d
世界历史上第一个这样有缺陷的剧本。
myapp.service - SYSV:启动/停止我的应用程序的服务脚本
那个“SYSV:”有一个赠品表明你的init.d
脚本很差。它甚至没有 LSB 标头块。
正如汤姆·亨特所说,编写一些服务单元。或者记住迁移到 systemd 的第一条规则,然后去捏那些已经写好的规则。从表面上看,您实际上拥有三个相互依赖但不同的服务,并且应该编写多个服务单元来表达这些相互依赖关系。如果其中一个是侦听端口 3307 的数据库服务器,则几乎肯定适用第一条规则。