作为Write for DOnations计划的一部分,作者选择了免费和开源基金来接受捐赠。
介绍
在这个由两部分组成的教程中,您将学习如何使用systemd
.
第一部分涵盖了一般的 Linux 服务管理概念,如init
守护进程和运行级别。它以 .NET 中的服务管理演示结束systemd
。在这里,您将检查targets
,wants
,requires
,和unit
文件。
第二部分提供了用于完成实用和常见systemd
任务的分步教程。具体来说,您将配置 MySQL 数据库服务器以在崩溃或重新启动后自动启动。
注意:您也可以考虑阅读我们非常流行的使用systemctl
来控制 systemd 服务和单元的教程。
先决条件
要完成本教程,您需要:
- 运行 CentOS 8 的服务器,包括具有 sudo 权限的非 root 用户。要设置所有这些,包括防火墙,您可以创建一个运行 CentOS 8 的 DigitalOcean Droplet,然后按照我们的初始服务器设置指南进行操作。
介绍服务管理守护进程
Linux 服务可以在很大程度上通过改变服务管理守护进程(也称为守护进程)处理它们的方式来实现自我修复init
。
init
是在机器启动并且内核加载到内存后在 Linux 系统中启动的第一个进程。其中,它决定用户进程或系统服务应如何加载、以何种顺序加载以及是否应自动启动。
随着 Linux 的发展,init
守护进程的行为也在发展。最初,Linux 从 System V 开始,与init
Unix 中使用的相同。从那以后,Linux 实现了 Upstartinit
守护进程(由 Ubuntu 创建),现在是 systemdinit
守护进程(首先由 Fedora 实现)。
大多数现代 Linux 发行版已逐渐从 System V 迁移,目前使用 systemd。init
保留旧样式(如果使用)只是为了向后兼容。FreeBSD 是 UNIX 的一种变体,它使用不同的 System V 实现,称为 BSD init
。
我们将在本文中介绍 systemd,因为这是当今 Linux 发行版中使用的最新和最常见的服务管理器。然而,我们也会在必要时讨论 System V 和 Upstart,看看 systemd 是如何从那里演变而来的。给你一个想法:
- System V是最古老的
init
系统,用于- Debian 6 及更早版本
- Ubuntu 9.04 及更早版本
- CentOS 5 及更早版本
- Upstart出现在 System V 之后,被用于
- Ubuntu 9.10 到 Ubuntu 14.10,包括 Ubuntu 14.04
- CentOS 6
- systemd是最新的 Linux 服务管理器,用于
- Debian 7 及以上
- Ubuntu 15.04 及以上
- CentOS 7 及以上
为了理解init
守护进程,让我们从一个叫做runlevel 的东西开始。
运行级别
运行级别代表 Linux 系统的当前状态。例如,运行级别可以是 Linux 服务器的关闭状态、单用户模式、重新启动模式等。每种模式将指示哪些服务可以在该状态下运行。
某些服务可以在一个或多个运行级别中运行,但不能在其他运行级别中运行。运行级别由 0 到 6 之间的值表示。以下列表显示了每个级别的含义:
- 运行级别 0:系统关闭
- 运行级别 1:单用户,救援模式
- 运行级别 2、3、4:启用网络的多用户文本模式
- 运行级别 5:多用户、支持网络、图形模式
- 运行级别 6:系统重启
运行级别 2、3 和 4 因发行版而异。例如,一些 Linux 发行版没有实现运行级别 4,而其他发行版则实现了。一些分布在这三个级别之间有明显的区别。通常,运行级别 2、3 或 4 表示 Linux 以多用户、启用网络的文本模式启动的状态。
当您启用服务自动启动时,Linux 实际上是将它添加到运行级别。例如,在 System V 中,操作系统将以特定的运行级别启动;并且,当它启动时,它将尝试启动与该运行级别关联的所有服务。在 systemd 中,运行级别已成为目标,当服务自动启动时,它被添加到目标中。我们将在本文后面讨论目标。
System Vinit
守护进程简介
System V 使用一个inittab
文件,后来的init
方法为了向后兼容而保留了该文件。让我们来看看 System V 的启动顺序:
- 该
init
守护进程从二进制文件/ sbin目录/ init建立 init
守护进程读取的第一个文件是 /etc/inittab- 该文件中的条目之一决定了机器应该引导到的运行级别。例如,如果运行级别的值指定为 3,Linux 将在启用网络的多用户文本模式下启动。(此运行级别称为默认运行级别)
- 接下来,
init
守护进程进一步查看 /etc/inittab 文件并读取init
它需要为该运行级别运行的脚本
因此,当init
守护进程发现init
它需要为给定的运行级别运行哪些脚本时,它实际上是在找出它需要启动哪些服务。init
您可以在这些脚本中为各个服务配置启动行为。
一个init
脚本是什么在控制系统V特定的服务init
脚本服务是由应用程序的供应商提供或使用的Linux发行版(本机服务)来了。您还可以为init
自定义创建的服务创建自己的脚本。
当 MySQL Server 等进程或服务在 System V 下启动时,其二进制程序文件必须加载到内存中。根据服务的配置方式,该程序可能会持续执行后台(并接受客户端连接)。启动、停止或重新加载此二进制应用程序的工作由服务的init
脚本处理。init
之所以称为脚本,是因为它初始化了服务。
在 System V 中,init
脚本是一个 shell 脚本。它们也称为rc
(运行命令)脚本。脚本位于/etc/init.d
目录下。这些脚本符号链接到/etc/rc
目录。在/etc
目录中,有许多rc
目录,每个目录的名称中都有一个数字。数字代表不同的运行级别。所以我们有/etc/rc0.d
, /etc/rc1.d
,/etc/rc2.d
等等。
要在崩溃或重新启动后重新启动服务,通常可以在init
脚本中添加如下一行:
- ms:2345:respawn:/bin/sh /usr/bin/service_name
要在系统引导时启动 System V 服务,请运行以下命令:
- sudo chkconfig service_name on
要禁用它,请运行以下命令:
- sudo chkconfig service_name off
要检查状态(正在运行或已停止),请运行此命令
- sudo service service_name status
介绍新贵守护进程
随着 System V 加载作业和服务的序列化方式变得更加耗时和复杂,init
引入了 Upstart 守护进程以加快操作系统加载速度、优雅地清理崩溃的服务以及系统服务之间可预测的依赖关系。
Upstart在以下几个方面init
优于 System V init
:
- 它没有处理神秘的 shell 脚本来加载和管理服务。相反,它使用易于理解和修改的简单配置文件
- 服务不像 System V 那样串行加载,这减少了系统启动时间
- 它使用灵活的事件系统来自定义在各种状态下如何处理服务
- Upstart 有更好的方法来处理崩溃的服务应该如何重生。
- 没有必要保留许多冗余的符号链接,它们都指向同一个脚本
为简单起见,Upstart 向后兼容 System V。该/etc/init.d/rc
脚本仍运行以管理本机 System V 服务。它的主要区别在于它允许将多个事件与服务关联的方式。这种基于事件的架构使 Upstart 成为一个灵活的服务管理器。使用 Upstart,每个事件都可以触发处理该事件的 shell 脚本。这些事件包括:
- 开始
- 开始
- 停止
- 停止
在这些事件之间,服务可以处于多种状态,如等待、预启动、启动、运行、预停止、停止等。 Upstart 也可以对这些状态中的每一个采取行动,从而创建一个非常灵活的建筑学。
启动时,Upstart 将正常运行任何 System Vinit
脚本。然后它将在/etc/init
目录下查找并执行每个服务配置文件中的 shell 命令。除其他外,这些文件控制服务的启动行为。
这些文件的命名样式为service_name.conf
,并且它们具有包含不同部分的纯文本内容,称为节。每个节都描述了服务的不同方面以及它应该如何表现。要使服务在崩溃或重启后自动启动,您可以respawn
在其服务配置文件中添加该命令,如下所示的 cron 服务。
...
description "regular background program processing daemon"
start on runlevel [2345]
stop on runlevel [!2345]
expect fork
**respawn**
exec cron
介绍systemd
守护进程
最新的 Linuxinit
守护进程是 systemd。事实上,它不仅仅是一个init
守护进程:systemd 是一个包含现代 Linux 系统许多组件的框架。
它的功能之一是充当 Linux 的系统和服务管理器。在这种情况下,systemd 控制服务在崩溃或机器重新启动时的行为方式。您可以在此处阅读有关 systemd 的 systemctl 的信息。
systemd 向后兼容 System V 命令和初始化脚本。这意味着任何 System V 服务也将在 systemd 下运行。这是可能的,因为大多数 Upstart 和 System V 管理命令已被修改为在 systemd 下工作。
systemd 配置文件:单元文件
systemd 的核心是单元文件。每个单元文件代表一个特定的系统资源。在单元文件中跟踪有关资源的信息。服务单元文件是具有声明性语法的简单文本文件(如 Upstart .conf 文件)。这使文件易于理解和修改。
systemd 与其他两种init
方法的主要区别在于 systemd负责服务守护进程和其他类型的资源(如设备操作系统路径、挂载点、套接字等)的初始化。单元文件的命名风格是service_name.unit_type
. 所以,你会看到一个文件一样dbus.service
,sshd.socket
或home.mount
。
目录结构
在 CentOS 等基于 Red Hat 的系统中,单元文件位于两个位置。主要地点是/lib/systemd/system/
。自定义创建的单元文件或由系统管理员修改的现有单元文件将存在于/etc/systemd/system
.
如果两个位置都存在同名的单元文件,systemd 将使用/etc
. 假设服务被启用在启动时或任何其他目标/运行级别启动。在这种情况下,将为该服务单元文件在/etc/systemd/system
. 下的单元文件/etc/systemd/system
实际上是/lib/systemd/system
.下同名文件的符号链接。
systemdinit
序列:目标单位
一种特殊类型的单元文件是目标单元。
目标单元文件名以 .target 为后缀。目标单元与其他单元文件不同,因为它们不代表一种特定资源。相反,它们代表系统在任何时候的状态。目标单元通过分组和启动应该是该状态一部分的多个单元文件来做到这一点。因此,systemd 目标可以与 System V 运行级别进行粗略的比较,尽管它们并不相同。
每个目标都有一个名称而不是数字。例如,我们有multi-user.target
代替runlevel 3
或reboot.target
代替runlevel 6
。当 Linux 服务器以 , 启动时multi-user.target
,它本质上是将服务器带到runlevel 2, 3, or 4
,这是启用了网络的多用户文本模式。
不同之处在于它如何将服务器带到那个阶段。与 System V 不同,systemd 不会按顺序启动服务。在此过程中,它可以检查其他服务或资源的存在并决定它们的加载顺序。这使得服务可以并行加载。
目标单元和运行级别之间的另一个区别是,在 System V 中,Linux 系统只能存在于一个运行级别中。您可以更改运行级别,但系统将仅存在于该新运行级别中。使用 systemd,目标单元可以包含在内,这意味着当一个目标单元被激活时,它可以确保其他目标单元作为它的一部分被加载。
例如,使用图形用户界面启动的 Linux 系统将激活 graphics.target,这反过来将自动确保加载并激活 multi-user.target。在 System V 术语中,这就像同时激活运行级别 3 和 5。
下表比较了运行级别和目标:
运行级别(System V init) | 目标单位(Systemd) |
---|---|
运行级别 0 | 关机目标 |
运行级别 1 | 救援目标 |
运行级别 2、3、4 | 多用户目标 |
运行级别 5 | 图形目标 |
运行级别 6 | 重启目标 |
systemd default.target
systemddefault.target
相当于 System V 默认运行级别。
System V 在名为 inittab 的文件中定义了默认运行级别。在 systemd 中,该文件被 default.target 替换。默认的目标单元文件位于 /etc/systemd/system 目录下。它是 /lib/systemd/system 下目标单元文件之一的符号链接。
当您更改默认目标时,您实际上是在重新创建该符号链接并更改系统的运行级别。
System V 中的 inittab 文件还指定了 Linux 将从哪个目录执行其init
脚本:它可以是任何 rcn.d 目录。在 systemd 中,默认目标单元决定了在启动时将加载哪些资源单元。
当单元被激活时,它们全部并行或全部依次激活。资源单元如何加载可能取决于它想要或需要的其他资源单元。
systemd 依赖项:需要和需要
systemd想要并且需要控制 systemd 如何解决服务守护进程之间的依赖关系。
如前所述,Upstart 确保使用配置文件并行加载服务。在 System V 中,服务可以在特定的运行级别启动,但也可以等待另一个服务或资源可用。以类似的方式,可以使 systemd 服务加载到一个或多个目标中,或者等待另一个服务或资源变为活动状态。
在 systemd 中,需要另一个单元的单元在加载并激活所需单元之前不会启动。如果在第一个单元处于活动状态时所需的单元由于某种原因出现故障,第一个单元也将停止。
这确保了系统的稳定性。因此,可以使需要特定目录存在的服务等待,直到该目录的安装点处于活动状态。另一方面,想要另一个单位的单位不会施加此类限制。如果在呼叫者处于活动状态时所需的单元停止,它不会停止。这方面的一个例子是在图形目标模式下出现的非必要服务。
实际示例:了解 systemd 启动顺序
为了了解 systemd 下的服务启动行为,我们使用 CentOS 8.3 Droplet。我们将尽可能地遵循 .target rabbit-trail。systemd 的启动顺序遵循一长串依赖关系。
首先,让我们运行这个命令来列出默认的目标单元文件:
- sudo ls -l /etc/systemd/system/default.target
这将显示如下输出:
Outputlrwxrwxrwx. 1 root root 37 Dec 4 17:42 /etc/systemd/system/default.target -> /lib/systemd/system/multi-user.target
如您所见,默认目标实际上是指向 /lib/systemd/system/ 下的多用户目标文件的符号链接。因此,系统应该在 multi-user.target 下启动,这类似于 System V init 中的运行级别 3。
多用户.目标.想要
接下来,让我们运行以下命令来检查 multi-user.target 文件想要的所有服务:
- sudo ls -l /etc/systemd/system/multi-user.target.wants/*.service
这应该显示一个符号链接文件列表,指向 /usr/lib/systemd/system/ 下的实际单元文件:
Outputlrwxrwxrwx. 1 root root 38 Dec 4 17:38 /etc/systemd/system/multi-user.target.wants/auditd.service -> /usr/lib/systemd/system/auditd.service
lrwxrwxrwx. 1 root root 39 Dec 4 17:39 /etc/systemd/system/multi-user.target.wants/chronyd.service -> /usr/lib/systemd/system/chronyd.service
lrwxrwxrwx. 1 root root 37 Dec 4 17:38 /etc/systemd/system/multi-user.target.wants/crond.service -> /usr/lib/systemd/system/crond.service
lrwxrwxrwx. 1 root root 42 Dec 4 17:39 /etc/systemd/system/multi-user.target.wants/irqbalance.service -> /usr/lib/systemd/system/irqbalance.service
lrwxrwxrwx. 1 root root 37 Dec 4 17:41 /etc/systemd/system/multi-user.target.wants/kdump.service -> /usr/lib/systemd/system/kdump.service
...
除此之外multi-user.target
,还有不同类型的目标,例如system-update.target
或basic.target
。要查看多用户目标所依赖的目标,请运行以下命令:
- sudo systemctl show --property "Requires" multi-user.target | fmt -10
输出显示:
OutputRequires=basic.target
基本目标
您可以运行以下命令来查看 basic.target 是否有任何必需的单位:
- sudo systemctl show --property "Requires" basic.target | fmt -10
事实证明,basic.target 需要 sysinit.target:
OutputRequires=sysinit.target
-.mount
它也需要一些目标:
- sudo systemctl show --property "Wants" basic.target | fmt -10
该命令将返回以下内容:
OutputWants=slices.target
paths.target
timers.target
microcode.service
sockets.target
sysinit.target
递归地,您可以查看 sysinit.target 是否还需要运行任何其他目标:
- sudo systemctl show --property "Requires" sysinit.target | fmt -10
不会有。但是, sysinit.target 还需要其他目标:
- systemctl show --property "Wants" sysinit.target | fmt -10
将出现这样的输出:
OutputWants=systemd-random-seed.service
dev-mqueue.mount
rngd.service
systemd-modules-load.service
proc-sys-fs-binfmt_misc.automount
local-fs.target
sys-fs-fuse-connections.mount
systemd-sysusers.service
systemd-update-done.service
systemd-update-utmp.service
systemd-journal-flush.service
dev-hugepages.mount
dracut-shutdown.service
swap.target
systemd-udevd.service
import-state.service
sys-kernel-debug.mount
nis-domainname.service
systemd-journald.service
selinux-autorelabel-mark.service
kmod-static-nodes.service
loadmodules.service
ldconfig.service
cryptsetup.target
systemd-sysctl.service
systemd-ask-password-console.path
systemd-journal-catalog-update.service
systemd-udev-trigger.service
systemd-tmpfiles-setup.service
systemd-hwdb-update.service
sys-kernel-config.mount
systemd-binfmt.service
systemd-tmpfiles-setup-dev.service
systemd-machine-id-commit.service
systemd-firstboot.service
检查systemd
单元文件
现在更进一步,让我们看一下服务单元文件,即 sshd 文件:
- sudo vi /etc/systemd/system/multi-user.target.wants/sshd.service
它看起来像这样:
[Unit]
Description=OpenSSH server daemon
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target sshd-keygen.target
Wants=sshd-keygen.target
[Service]
Type=notify
EnvironmentFile=-/etc/crypto-policies/back-ends/opensshserver.config
EnvironmentFile=-/etc/sysconfig/sshd
ExecStart=/usr/sbin/sshd -D $OPTIONS $CRYPTO_POLICY
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s
[Install]
WantedBy=multi-user.target
您可以看到服务单元文件干净且易于理解。
第一个重要部分是部分中的 After 子句[Unit]
。这表示 sshd 服务需要在 network.target 和 sshd-keygen.target 加载后加载。
该[Install]
部分显示 multi-user.target 需要该服务。这意味着 multi-user.target 将加载 sshd 守护进程,但如果 sshd 在加载过程中失败,它不会关闭或崩溃。
由于multi-user.target
是默认目标,sshd 守护进程应该在引导时启动。在该[Service]
部分中,该Restart
参数的值为on-failure
。此设置允许 sshd 守护进程在崩溃或不干净的退出时重新启动。
结论
在本文中,您了解了 System V、Upstart 和 systemd 服务管理守护进程。您探索了启动脚本和配置文件、重要参数、启动顺序以及控制服务启动行为的命令。
在本文的第二部分,我们将把这些技巧应用到一个真实的例子中,并使用 systemd 来配置 MySQL。完成后,您的 MySQL 实例将在重启或崩溃后自动重启。虽然您将使用 MySQL 作为示例应用程序,但您可以替换任意数量的服务,例如 Nginx 或 Apache Web 服务器。