如何在RHEL/CentOS 7上自动启动服务?

想知道如何在后台或开机时管理服务?

管理和启动进程的机制已经改变。在RHEL/CentOS 6.x之前,你需要在/etc/init.d/目录下创建一个脚本,并使用chkconfig命令来启用,但在RHEL 7上情况有所不同。

它被systemd取代了。由于它在主要Linux版本上基本上是默认的进程管理器,熟悉其他发行版的人会感到非常亲切。在本文中,我们将探讨systemd是什么,为什么要进行切换,以及如何使用systemd来设置、运行和管理后台进程。

systemd是什么?

由于Linux中的每个进程都是透明可见的,让我们看看systemd隐藏在哪里。在我的系统上,我得到了以下输出:

~$ ps -ef | grep systemd
root         1     0  0 Nov11 ?        00:01:02 /lib/systemd/systemd --system --deserialize 22
message+   768     1  0 Nov11 ?        00:05:46 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
root       805     1  0 Nov11 ?        00:10:22 /lib/systemd/systemd-logind
ankush    1132     1  0 Nov11 ?        00:00:00 /lib/systemd/systemd --user
ankush    1176  1132  0 Nov11 ?        00:04:50 /usr/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
ankush    9772 20029  0 21:11 pts/6    00:00:00 grep --color=auto systemd
systemd+ 17298     1  0 Nov19 ?        00:00:12 /lib/systemd/systemd-resolved
systemd+ 17303     1  0 Nov19 ?        00:00:00 /lib/systemd/systemd-timesyncd
root     17307     1  0 Nov19 ?        00:00:02 /lib/systemd/systemd-journald
root     18182     1  0 Nov19 ?        00:00:00 /lib/systemd/systemd-udevd

我敢打赌你立刻注意到了它。列表中的第一个进程是以用户root启动的,进程ID为1。

毫无疑问,这是系统在启动时启动的第一个进程。欢迎来到systemd。🙂

所以,简单来说,systemd是在系统中启动、管理和终止其他进程的“母”进程,同时提供有关它们的日志、文件系统状态等信息。

不过,关于名称的说明。名称确实是systemd,而不是System D或其他任何名称。这里的“d”代表daemon,即一个标准的Linux进程,它在后台运行而不附加到任何终端会话。

RHEL为什么切换到systemd?

正如我们已经讨论过的,systemd是一个系统和进程管理器,在RHEL 7中取代了著名的Upstart程序。为什么RHEL做出了这个决定?嗯,有很好的理由,让我们快速看一下。

并行服务初始化

与SysV的init程序不同,systemd能够并行启动服务。相比之下,init程序是一个一个地启动它们的。在如今甚至移动设备都拥有多核CPU的时代,缺乏并行初始化是一个巨大的缺点。

动态(热)服务管理

如果你注意到之前的Fedora系统上需要显式挂载USB驱动器,而在Ubuntu和类似的发行版上它们会自动弹出,原因就是systemd。它能够检测到硬件的实时变化,并根据需要终止/启动服务。有人可能会说这是不必要的,但对于许多人来说,减少认知负担的事情是非常受欢迎的。

延迟服务启动

systemd使启动时间更短,因为它能够将服务的启动推迟到真正需要的时候。一个简单的例子是与网络文件系统相关的服务。如果没有可用的网络磁盘,启动和运行服务就没有意义。

更快的进程通信

systemd的并行能力可以延伸到进程间通信。 systemd能够并行访问套接字和系统总线,从而显著减少进程等待通信资源的时间。

自动重启

如果服务崩溃,systemd可以检测到并尝试重新启动它。大多数情况下,只需要简单地重新启动应用程序,即可使其再次正常运行,除非存在更基本的问题。

无论如何,systemd在这方面使系统管理员的工作更轻松。

RHEL7中的systemd-系统管理员有什么变化?

如果你有一种强烈的感觉,认为systemd不会带来一切的便利,那么你是对的。有一些重要的不兼容性可能会让RHEL系统管理员感到意外。让我们来快速看一下。

有限的运行级别支持

systemd对运行级别的识别和支持相当差劲。并非所有的运行级别都受支持,对于某些目标甚至可能没有任何运行级别。在这种情况下,systemdrunlevel命令的回应是“N”,表示它没有与该目标对应的运行级别。总的来说,Red Hat建议我们不要使用runlevel命令。

没有自定义命令

这一点可能会让人感到困扰。SysV的一个重要优点是能够定义自定义命令,以提供更好的进程管理功能。而在systemd中,没有这样的选项,只能使用startstopstatusrestart等命令。

仅限家族和非交互式

systemd(当然)会跟踪它启动的进程并存储它们的PID。然而,挑战在于systemd无法处理它没有启动的进程。此外,用户无法与由systemd启动的进程进行交互。所有输出都会被重定向到/dev/null,有效地阻止了你可能希望捕获输出的任何希望。

没有上下文

init服务不同,由systemd启动的服务不会继承系统中任何用户的环境。换句话说,像PATH和其他系统变量这样的信息是不可用的,每个新进程都在空的上下文中启动。

如果这个限制列表让你难过,那么你并不孤单。 systemd在Linux世界中一直是一个有争议的力量,搜索“systemd sucks”会找到大量的阅读材料。

如何在服务停止时自动启动服务?

这是一个在部署中非常常见的用例。我们需要将一个没有长时间运行过程的程序守护化:PHP!假设我编写了一个处理传入的websocket连接的PHP脚本(毕竟我们构建了一个聊天应用),并将该脚本放置在/home/ankush/chat_server/index.php

由于websocket连接可以随时连接服务器,所以这个进程需要始终处于运行状态并监控传入的连接。我们无法使用传统的PHP生命周期,因为WebSockets是有状态的连接,如果脚本停止运行,连接也会断开。总之,关于WebSockets的内容就这么多,现在让我们看看如何通过systemd将此脚本守护化。

所有的systemd服务都位于/etc/systemd/system目录中,因此让我们在那里创建一个文件来描述我们的websocket服务器脚本。假设你以root用户身份登录。

# vi /etc/systemd/system/chat_server.service

然后需要添加以下内容。

保存该文件,下一步是重新加载systemd守护进程。

# systemctl daemon-reload

然后启动我们刚刚创建的服务:

# systemctl start chat_server

如果没有出现错误,就完成了!

让我们快速看一下文件中各个指令的含义:

– [Unit] 部分定义了一个新的systemd服务单元。在systemd的术语中,所有服务都被称为服务单元。
– After指令(预测)告诉systemd仅在网络服务启动后才启动该服务(否则,谁来处理低层的套接字连接?!)。
– Type=simple告诉systemd该服务不会分叉。换句话说,任何时候只会运行一个实例。
– User=ankush表示该服务将以用户“ankush”的身份运行。我们可以将其更改为“root”,但从安全的角度来看,这是非常不推荐的。
– ExecStart,正如你所看到的,是实际要运行的命令。
– Restart=on-abort表示该服务在中止时应重新启动。在PHP中,长时间运行的进程会泄露内存并最终崩溃,所以这是必需的。
– WantedBy指令告诉systemd该服务是哪个目标(类似于组)的一部分。这会导致在该目标内创建指向该服务的符号链接。

通常,使用systemd在RHEL 7中运行后台进程就足够了。

重新启动逻辑的更多选项

在上面的示例中,我配置了Restart=on-abort,但这并不是唯一的选项。还有更多选项,可以根据需求进行选择。

– on-failure – 在出现非正常退出代码或信号时重新启动
– always – 在发现服务停止时,无论是否为正常或非正常信号,都会重新启动
– on-abnormal – 非正常信号、看门狗或超时
– on-success – 仅在服务被干净的信号或退出代码停止时重新启动

配置服务在启动时启动

一旦你对脚本满意并确保它正常工作,下一步就是配置它在启动时触发并启动。

进入/etc/systemd/system并执行以下启用命令(不要忘记将.service文件名更改为你自己的)。

# systemctl enable chat_server.service

你会看到一个确认消息,说明它已经创建了一个符号链接。

Created symlink from /etc/systemd/system/multi-user.target.wants/chat_server.service to /etc/systemd/system/chat_server.service.

重新启动服务器,你应该看到服务在启动时启动。

这很简单!不是吗?

帮助!我对Upstart非常投入。 🙁

我知道你相信我,你的情况是正常的而不是例外。RHEL长时间使用Upstart,因此转换几乎感觉像是一种背叛。但是嘿,系统一直在变化,我们不应为琐事而争吵。Red Hat认识到许多人还停留在旧版本上,并创建了一个链接_3,你一定要参考一下。

在所有这些中唯一的拯救之处是,systemd与SysV init脚本兼容,因此在大多数情况下,你只需要移动文件并获得相同的服务运行。

有兴趣了解更多关于Linux管理和故障排除的知识吗?查看这个链接_4。

类似文章