systemd - 是的,所有小写,即使在句子的开头 - 是 init 和 SystemV init 脚本的现代替代品。它也远不止于此。
像大多数系统管理员一样,当我想到 init 程序和 SystemV 时,我想到的是 Linux 的启动和关闭,而实际上没有太多其他的事情,比如管理服务一旦它们启动并运行。像 init 一样,systemd 是所有进程之母,它负责将 Linux 主机启动到可以进行高效工作的状态。systemd 所承担的一些功能,远比旧的 init 程序广泛得多,包括管理正在运行的 Linux 主机的许多方面,包括挂载文件系统、管理硬件、处理计时器,以及启动和管理拥有高效 Linux 主机所必需的系统服务。
本系列文章,部分基于我三卷 Linux 培训课程 使用和管理 Linux:从零到系统管理员 中的摘录,探讨了 systemd 在启动时以及启动完成后开始的功能。
Linux 启动
The 将 Linux 主机从关闭状态变为运行状态的完整过程非常复杂,但它是开放的且可知的。在深入细节之前,我将从主机硬件开启到系统准备好让用户登录时,给出一个快速概述。大多数时候,“启动过程”被作为一个单一的实体来讨论,但这是不准确的。实际上,完整的启动和启动过程有三个主要部分
- 硬件启动:初始化系统硬件
- Linux 启动:加载 Linux 内核,然后加载 systemd
- Linux 启动:systemd 在此准备主机以进行高效工作
Linux 启动序列在内核加载 init 或 systemd 之后开始,具体取决于发行版是使用旧的还是新的启动方式。init 和 systemd 程序启动和管理所有其他进程,并且在各自的系统中都被称为“所有进程之母”。
重要的是将硬件启动与 Linux 启动与 Linux 启动分开,并明确定义它们之间的分界点。了解这些差异以及每个部分在使 Linux 系统达到可以高效工作的状态中所起的作用,使得能够管理这些过程并更好地确定在大多数人所说的“启动”期间发生问题的位置。
启动过程遵循三步启动过程,并将 Linux 计算机启动到可用于高效工作的可操作状态。当内核将主机的控制权转移到 systemd 时,启动过程开始。
systemd 争议
systemd 可能会引起系统管理员和其他负责保持 Linux 系统运行的人员的广泛反应。事实上,systemd 正在接管许多 Linux 系统中的许多任务,这引起了一些开发人员和系统管理员的抵制和不和谐。
SystemV 和 systemd 是执行 Linux 启动序列的两种不同方法。SystemV 启动脚本和 init 程序是旧方法,而使用目标的 systemd 是新方法。尽管大多数现代 Linux 发行版使用较新的 systemd 进行启动、关闭和进程管理,但仍然有一些发行版没有这样做。一个原因是某些发行版维护人员和一些系统管理员更喜欢旧的 SystemV 方法而不是较新的 systemd。
我认为两者都有优势。
我为什么更喜欢 SystemV
我更喜欢 SystemV,因为它更开放。启动是使用 Bash 脚本完成的。内核启动 init 程序(这是一个编译后的二进制文件)后,init 启动 rc.sysinit 脚本,该脚本执行许多系统初始化任务。在 rc.sysinit 完成后,init 启动 /etc/rc.d/rc 脚本,该脚本又启动 /etc/rc.d/rcX.d 中 SystemV 启动脚本定义的各种服务,其中“X”是正在启动的运行级别的编号。
除了 init 程序本身,所有这些程序都是开放的且易于理解的脚本。可以通读这些脚本并准确了解整个启动过程中发生了什么,但我不认为很多系统管理员实际上会这样做。每个启动脚本都已编号,以便按特定顺序启动其预期的服务。服务是串行启动的,一次只启动一个服务。
systemd 由 Red Hat 的 Lennart Poettering 和 Kay Sievers 开发,是一个复杂的系统,由大型、编译的二进制可执行文件组成,如果没有访问源代码,就无法理解。它是开源的,因此“访问源代码”并不难,只是不太方便。systemd 似乎代表了对 Linux 哲学多个信条的重大驳斥。作为二进制文件,systemd 不直接向系统管理员开放以查看或进行轻松更改。systemd 试图做所有事情,例如管理正在运行的服务,同时提供比 SystemV 明显更多的状态信息。它还管理硬件、进程和进程组、文件系统挂载等等。systemd 几乎存在于现代 Linux 主机的每个方面,使其成为系统管理的一站式工具。所有这些都明显违反了程序应该很小且每个程序应该做一件事并做好这一点的信条。
我为什么更喜欢 systemd
我更喜欢 systemd 作为我的启动机制,因为它根据启动过程的当前阶段并行启动尽可能多的服务。这加快了整体启动速度,并使主机系统比 SystemV 更快地进入登录屏幕。
systemd 管理着正在运行的 Linux 系统的几乎每个方面。它可以管理正在运行的服务,同时提供比 SystemV 明显更多的状态信息。它还管理硬件、进程和进程组、文件系统挂载等等。systemd 几乎存在于现代 Linux 操作系统的每个方面,使其成为系统管理的一站式工具。(这听起来很熟悉吗?)
systemd 工具是编译后的二进制文件,但该工具套件是开放的,因为所有配置文件都是 ASCII 文本文件。可以通过各种 GUI 和命令行工具修改启动配置,以及添加或修改各种配置文件以满足特定本地计算环境的需求。
真正的问题
你认为我不能同时喜欢这两种启动系统吗?我喜欢,而且我可以与任何一个系统一起工作。
在我看来,SystemV 和 systemd 之间的大部分争议的真正问题和根本原因是系统管理员级别没有选择。是否使用 SystemV 或 systemd 的选择已经由各种发行版的开发人员、维护人员和打包人员做出 - 但这是有充分理由的。由于其极端、侵入性的性质,铲出和替换 init 系统会产生很多难以在发行版设计过程之外解决的后果。
尽管这个选择是为我做的,但我的 Linux 主机可以启动并工作,这通常是我最关心的。作为最终用户,甚至作为系统管理员,我最关心的是我是否可以完成我的工作,比如写我的书和这篇文章,安装更新,以及编写脚本来自动化一切。只要我能完成我的工作,我就不太关心我的发行版上使用的启动序列。
当启动或服务管理过程中出现问题时,我确实会关心。无论主机上使用哪种启动系统,我都了解足够多,可以按照事件的顺序找到故障并修复它。
替换 SystemV
以前曾尝试用更现代的东西替换 SystemV。大约两个版本,Fedora 使用了一个名为 Upstart 的东西来替换老化的 SystemV,但它没有替换 init,也没有提供我注意到的任何更改。由于 Upstart 没有为围绕 SystemV 的问题提供任何重大更改,因此很快就放弃了朝这个方向的努力,转而支持 systemd。
尽管大多数 Linux 开发人员都同意替换旧的 SystemV 启动是个好主意,但许多开发人员和系统管理员不喜欢 systemd。与其重新讨论人们对 systemd 存在 - 或曾经存在 - 的所有所谓问题,我将你推荐给两篇好的,如果有点旧的文章,它们应该涵盖几乎所有内容。Linux 内核的创建者 Linus Torvalds 似乎不感兴趣。在 2014 年 ZDNet 的文章 Linus Torvalds 和其他关于 Linux systemd 的人 中,Linus 清楚地表达了他的感受。
“我实际上对 systemd 本身没有任何特别强烈的意见。我对一些核心开发人员存在问题,我认为他们在错误和兼容性方面过于草率,我认为一些设计细节很疯狂(例如,我不喜欢二进制日志),但这些都是细节,而不是大问题。”
如果您对 Linus 了解不多,我可以告诉你,如果他不喜欢某些东西,他会非常直言不讳、明确且非常清楚地表达这种不喜欢。他在解决他对事物的不喜欢的方式上变得更具有社会接受度。
在 2013 年,Poettering 发表了一篇长篇博文,他在其中驳斥了关于 systemd 的神话,同时提供了创建它的一些原因的见解。这是一篇非常值得一读的文章,我强烈推荐它。
systemd 任务
根据编译过程中使用的选项(本系列文章未考虑),systemd 可以有多达 69 个二进制可执行文件,它们执行以下任务,以及其他任务
- systemd 程序以 PID 1 运行,并尽可能并行地提供尽可能多的服务的系统启动,这作为副作用,加快了整体启动时间。它还管理关闭序列。
- systemctl 程序为服务管理提供用户界面。
- 为了向后兼容,提供了对 SystemV 和 LSB 启动脚本的支持。
- 服务管理和报告提供了比 SystemV 更多的服务状态数据。
- 它包含用于基本系统配置的工具,例如主机名、日期、区域设置、已登录用户列表、正在运行的容器和虚拟机、系统帐户、运行时目录和设置、用于管理简单网络配置的守护进程、网络时间同步、日志转发和名称解析。
- 它提供套接字管理。
- systemd 定时器提供高级的类似 cron 的功能,包括在相对于系统启动、systemd 启动、上次定时器启动时间等时间运行脚本。
- 它提供了一个工具来分析定时器规范中使用的日期和时间。
- 具有分层意识的文件系统的挂载和卸载允许更安全地级联挂载的文件系统。
- 它能够积极地创建和管理临时文件,包括删除。
- 到 D-Bus 的接口提供了在插入或移除设备时运行脚本的能力。这允许将所有设备(无论是否可插拔)都视为即插即用设备,从而大大简化了设备处理。
- 它的启动顺序分析工具可用于定位花费时间最多的服务。
- 它包括用于存储系统日志消息的日志以及用于管理日志的工具。
架构
这些任务以及更多任务由许多守护进程、控制程序和配置文件提供支持。图 1 显示了属于 systemd 的许多组件。这是一个简化的图,旨在提供一个高级概述,因此它不包括所有单独的程序或文件。它也没有提供对数据流的任何深入了解,数据流非常复杂,在本系列文章中进行研究将毫无意义。

图 1:systemd 的架构,作者:Shmuel Csaba Otto Traian (CC BY-SA 3.0)
图 1:systemd 的架构,作者:Shmuel Csaba Otto Traian (CC BY-SA 3.0)
对 systemd 的完整阐述本身就需要一本书。您无需了解图 1 中 systemd 组件如何组合在一起的详细信息;只需了解启用管理各种 Linux 服务以及处理日志文件和日志的程序和组件即可。但很明显,systemd 并不是一些批评者所说的整体性的庞然大物。
作为 PID 1 的 systemd
systemd 是 PID 1。它的一些功能(比旧的 SystemV3 init 程序广泛得多)是管理运行中的 Linux 主机的许多方面,包括挂载文件系统以及启动和管理运行一个生产力 Linux 主机所需的系统服务。systemd 的任何与启动顺序无关的任务都不在本篇文章的讨论范围内(但有些内容将在本系列的后面部分进行探讨)。
首先,systemd 挂载由 /etc/fstab 定义的文件系统,包括任何交换文件或分区。此时,它可以访问位于 /etc 中的配置文件,包括它自己的配置文件。它使用其配置链接 /etc/systemd/system/default.target 来确定应该将主机启动到哪种状态或目标。default.target 文件是指向真实目标文件的符号链接。对于桌面工作站,这通常是 graphical.target,它等效于 SystemV 中的运行级别 5。对于服务器,默认值更可能是 multi-user.target,它类似于 SystemV 中的运行级别 3。emergency.target 类似于单用户模式。目标和服务是 systemd 单元。
下表(图 2)比较了 systemd 目标与旧的 SystemV 启动运行级别。systemd 提供了 systemd 目标别名以实现向后兼容性。目标别名允许脚本和许多系统管理员使用 SystemV 命令(如 init 3)来更改运行级别。当然,SystemV 命令会被转发到 systemd 进行解释和执行。
systemd 目标 | SystemV 运行级别 | 目标别名 | 描述 |
default.target | 此目标始终使用符号链接别名为 multi-user.target 或 graphical.target。systemd 始终使用 default.target 来启动系统。default.target 永远不应别名为 halt.target、poweroff.target 或 reboot.target。 | ||
graphical.target | 5 | runlevel5.target | 具有 GUI 的 Multi-user.target |
4 | runlevel4.target | 未使用。在 SystemV 世界中,运行级别 4 与运行级别 3 相同。可以创建和自定义此目标以启动本地服务,而无需更改默认的 multi-user.target。 | |
multi-user.target | 3 | runlevel3.target | 所有服务都在运行,但仅限命令行界面 (CLI) |
2 | runlevel2.target | 多用户,没有 NFS,但所有其他非 GUI 服务都在运行 | |
rescue.target | 1 | runlevel1.target | 一个基本系统,包括挂载文件系统,仅运行最基本的服务,并在主控制台上提供一个救援 shell |
emergency.target | S | 单用户模式——没有服务运行;文件系统未挂载。这是最基本的操作级别,只有紧急 shell 在主控制台上运行,供用户与系统交互。 | |
halt.target | 停止系统,但不关闭电源 | ||
reboot.target | 6 | runlevel6.target | 重启 |
poweroff.target | 0 | runlevel0.target | 停止系统并关闭电源 |
图 2:SystemV 运行级别与 systemd 目标和一些目标别名的比较
每个目标在其配置文件中都有一组依赖项描述。 systemd 启动所需的依赖项,这些依赖项是在特定功能级别运行 Linux 主机所需的服务。当目标配置文件中列出的所有依赖项都已加载并运行时,系统将在该目标级别运行。在图 2 中,功能最多的目标位于表格的顶部,而功能从上到下逐渐减少。
systemd 还查看旧的 SystemV init 目录,以查看其中是否存在任何启动文件。如果是,systemd 会将它们用作配置文件来启动文件描述的服务。已弃用的 network 服务就是一个很好的例子,它仍然在 Fedora 中使用 SystemV 启动文件。
图 3(如下)直接从启动 man 页面复制而来。它显示了 systemd 启动期间的一般事件序列图,以及确保成功启动的基本排序要求。
cryptsetup-pre.target
|
(various low-level v
API VFS mounts: (various cryptsetup devices...)
mqueue, configfs, | |
debugfs, ...) v |
| cryptsetup.target |
| (various swap | | remote-fs-pre.target
| devices...) | | | |
| | | | | v
| v local-fs-pre.target | | | (network file systems)
| swap.target | | v v |
| | v | remote-cryptsetup.target |
| | (various low-level (various mounts and | | |
| | services: udevd, fsck services...) | | remote-fs.target
| | tmpfiles, random | | | /
| | seed, sysctl, ...) v | | /
| | | local-fs.target | | /
| | | | | | /
\____|______|_______________ ______|___________/ | /
\ / | /
v | /
sysinit.target | /
| | /
______________________/|\_____________________ | /
/ | | | \ | /
| | | | | | /
v v | v | | /
(various (various | (various | |/
timers...) paths...) | sockets...) | |
| | | | | |
v v | v | |
timers.target paths.target | sockets.target | |
| | | | v |
v \_______ | _____/ rescue.service |
\|/ | |
v v |
basic.target rescue.target |
| |
________v____________________ |
/ | \ |
| | | |
v v v |
display- (various system (various system |
manager.service services services) |
| required for | |
| graphical UIs) v v
| | multi-user.target
emergency.service | | |
| \_____________ | _____________/
v \|/
emergency.target v
graphical.target
图 3:systemd 启动图
sysinit.target 和 basic.target 目标可以被认为是启动过程中的检查点。尽管 systemd 的设计目标之一是并行启动系统服务,但在其他服务和目标启动之前,必须启动某些服务和功能目标。在满足该检查点所需的所有服务和目标之前,无法通过这些检查点。
当它依赖的所有单元都完成时,就会达到 sysinit.target 。所有这些单元,挂载文件系统、设置交换文件、启动 udev、设置随机生成器种子、启动底层服务以及设置加密服务(如果一个或多个文件系统已加密),都必须完成,但在 sysinit.target 中,可以并行执行这些任务。
sysinit.target 启动系统要达到最低限度的功能所需的以及启用移动到 basic.target 所需的所有底层服务和单元。
在满足 sysinit.target 之后,systemd 然后启动满足下一个目标所需的所有单元。基本目标通过启动所有后续目标所需的单元来提供一些附加功能。这些包括设置诸如到各种可执行目录的路径、通信套接字和定时器之类的内容。
最后,可以初始化用户级别的目标,multi-user.target 或 graphical.target。必须先达到 multi-user.target,然后才能满足图形目标依赖项。图 3 中带下划线的目标是通常的启动目标。当达到这些目标之一时,启动就完成了。如果 multi-user.target 是默认值,那么您应该在控制台上看到文本模式的登录。如果 graphical.target 是默认值,那么您应该看到一个图形登录;您看到的特定 GUI 登录屏幕取决于您的默认显示管理器。
启动 man 页面还描述并提供了启动到初始 RAM 磁盘和 systemd 关闭过程的图。
systemd 还提供了一个工具,用于列出完整启动的依赖项或指定单元的依赖项。单元是一个可控制的 systemd 资源实体,范围可以从特定服务(如 httpd 或 sshd)到定时器、挂载、套接字等。尝试以下命令并滚动浏览结果。
systemctl list-dependencies graphical.target
请注意,这完全扩展了将系统启动到图形目标运行模式所需的顶级目标单元列表。使用 --all 选项也可以展开所有其他单元。
systemctl list-dependencies --all graphical.target
您可以使用 less 命令的搜索工具搜索诸如 "target"、"slice" 和 "socket" 之类的字符串。
所以现在,尝试以下操作。
systemctl list-dependencies multi-user.target
和
systemctl list-dependencies rescue.target
和
systemctl list-dependencies local-fs.target
和
systemctl list-dependencies dbus.service
此工具可以帮助我可视化我正在处理的主机的启动依赖项的详细信息。继续花一些时间探索一个或多个 Linux 主机的启动树。但请小心,因为 systemctl man 页面包含以下注释
“请注意,此命令仅列出服务管理器当前加载到内存中的单元。特别是,此命令不适合获取特定单元上所有反向依赖项的综合列表,因为它不会列出当前未加载的单元声明的依赖项。”
最后的想法
即使在深入了解 systemd 之前,很明显它既强大又复杂。同样明显的是,systemd 不是一个单独的、巨大的、整体的且不可知的二进制文件。相反,它由许多较小的组件和子命令组成,这些组件和子命令旨在执行特定任务。
本系列的下一篇文章将更详细地探讨 systemd 启动,以及 systemd 配置文件、更改默认目标以及如何创建简单服务单元。
资源
互联网上提供了大量关于 systemd 的信息,但其中大部分内容都简洁、晦涩,甚至具有误导性。除了本文中提到的资源外,以下网页还提供了关于 systemd 启动的更详细和可靠的信息。
- Fedora 项目有一个很好的、实用的 指南systemd 入门。它几乎包含了您需要知道的所有信息,以便使用 systemd 配置、管理和维护 Fedora 计算机。
- Fedora 项目还有一个很好的 速查表,它将旧的 SystemV 命令与可比较的 systemd 命令交叉引用。
- 有关 systemd 的详细技术信息以及创建它的原因,请查看 Freedesktop.org 的 systemd 描述。
- Linux.com 的“更多 systemd 乐趣”提供了更高级的 systemd 信息和技巧。
Lennart Poettering(systemd 的设计师和主要开发者)还为 Linux 系统管理员撰写了一系列深入的技术文章。这些文章写于 2010 年 4 月至 2011 年 9 月之间,但它们现在和当时一样重要。其他所有关于 systemd 及其生态系统的优秀文章都基于这些论文。
21 条评论