理解 Systemd Targets:核心概念解析

揭开 systemd targets 的神秘面纱,它们是定义和管理 Linux 系统状态的强大 systemd 单元。本综合指南将解释 targets 如何组织服务和其他单元,协调启动过程,并为传统的运行级别提供现代化的替代方案。了解常见的 targets,如 `multi-user.target` 和 `graphical.target`,如何查看和更改默认 target,在运行时切换 target,甚至为您的应用程序创建自定义 targets。实用命令和最佳实践均包含在内,以帮助您有效地管理您的 systemd 驱动的 Linux 环境。

33 浏览量

理解 Systemd Targets:核心概念解析

Systemd 已成为大多数 Linux 发行版的默认 init 系统,彻底改变了服务和进程的管理方式。Systemd 复杂的系统初始化和状态管理能力的核心在于 targets 的概念。Targets 不仅仅是一系列服务的集合,它们是特殊的 systemd unit,用于定义期望的系统状态,并在启动过程及之后充当同步点。

本文旨在揭开 systemd targets 的神秘面纱,解释它们在组织其他 unit 和控制系统整体状态方面的基本作用。我们将探讨 targets 与传统 runlevel 的关系,详细介绍您会遇到的最常见 targets,并提供用于与之交互和管理的实用命令。到最后,您将清晰地理解 targets 如何协调您的系统从开机到完全运行环境的整个过程。

什么是 Systemd Targets?

在 systemd 生态系统中,target 是一种特殊的 unit 文件(类似于 .service.socket 文件),它具有关键的组织目的。与定义如何启动或停止特定进程的服务 unit 不同,target unit 定义的是一个系统状态一组应同时激活的 unit。它们充当其他 systemd unit 的逻辑分组点和同步点。

将 targets 想象成系统运行过程中的里程碑。Systemd 启动时,并非随意启动服务列表;它会朝着实现特定 target 努力。这个 target 反过来会引入实现该状态所需的所有必要服务、sockets、挂载点和其他 targets。这种依赖驱动的方法确保了可预测且高效的启动过程。

对于熟悉 SysVinit 等旧版 Linux init 系统的人来说,systemd targets 是 runlevels 的现代等价物。虽然 SysVinit 有一套固定的 runlevel(例如,runlevel 3 用于多用户文本模式,runlevel 5 用于多用户图形模式),但 systemd targets 更为灵活。它们是命名的,而非编号的,您可以定义自定义 targets,从而提供更大的粒度和可扩展性。

Targets 如何工作:分组和依赖

Targets 通过在其 unit 文件中定义的显式依赖关系来实现其分组和状态定义能力。主要用于此目的的指令是 Wants=Requires=After=Before=

  • Wants=: 指定“弱”依赖。如果 target A Wants= unit B,则在激活 target A 时,systemd 将尝试启动 unit B。但是,即使 unit B 启动失败,target A 仍会启动。这通常用于组织相关但并非严格必需的服务。
  • Requires=: 指定“强”依赖。如果 target A Requires= unit B,则必须成功启动 unit B 才能激活 target A。如果 unit B 失败,target A 也会失败或不启动。这用于关键依赖。
  • After=: 定义排序依赖。如果 target AAfter= unit B,则 target A 只会在 unit B 启动之后启动。这并不表示成功依赖,仅表示顺序。
  • Before=: After= 的反向。如果 target ABefore= unit B,则 unit B 只会在 target A 启动之后启动。
  • Conflicts=: 确保某些 unit 不会同时激活。如果 target A Conflicts= unit B,则激活 target A 会停止正在运行的 unit B,反之亦然。

这些指令允许 targets 作为强大的编排器,根据需要引入服务和其他 targets,并定义它们的启动顺序。例如,multi-user.target 通常 Wants= network.target 和各种其他服务,确保在系统达到多用户状态时它们处于激活状态。

您可以通过检查 target unit 文件内容来查看其依赖关系:

systemctl cat multi-user.target

此命令将输出 multi-user.target unit 文件的内容,显示其 DescriptionDocumentation,以及最重要的 Wants=Requires=After= 和其他定义多用户状态的指令。

常见 Systemd Targets 详解

Systemd 提供了多种预定义 targets,每种都对应特定的系统状态或功能。理解这些对于系统管理至关重要:

  • default.target: 这是最重要的 target,因为它定义了您的系统启动的默认状态。它通常是 graphical.target(用于桌面)或 multi-user.target(用于服务器)的符号链接。
  • graphical.target: 此 target 通常用于具有图形桌面环境的系统。它会引入 multi-user.target,然后添加图形登录管理器和显示服务器(例如 GDM、LightDM、Xorg、Wayland)所需的 ist services。
  • multi-user.target: 这是没有图形界面的多用户系统的标准状态。它通常用于服务器,并提供命令行访问、网络和大多数守护进程操作所需的所有必要服务。
  • basic.target: 一个最小状态,包括了基本系统操作所需的 ist basic system services,但早于 multi-user.target。它通常会引入 sysinit.target 和其他基本服务。
  • sysinit.target: 此 target 在启动过程的早期达到。它负责核心系统初始化任务,如挂载 /etc/fstab 文件系统(不包括远程文件系统)、设置 swap 和其他与硬件相关的初始化。
  • local-fs.target: 确保 /etc/fstab 中指定的所有本地文件系统都已挂载。
  • remote-fs.target: 确保 /etc/fstab 中指定的所有远程文件系统(例如 NFS、CIFS)都已挂载。
  • network.target: 表明基本的网络连接可用(例如,网络接口已启动)。它不保证完全的互联网连接或 IP 地址分配。
  • network-online.target: 一个更健壮的网络 target,表明系统具有完整的网络连接,包括分配的 IP 地址和可能可达的网关。需要主动互联网访问的服务应 After=network-online.target
  • rescue.target: 提供一个单用户 shell,运行的服务最少,并且本地文件系统已挂载。用于系统恢复和故障排除。
  • emergency.target: 比 rescue.target 更minimal的环境。它在根文件系统上提供一个 shell,该文件系统通常以只读方式挂载。不启动任何其他服务。用于关键紧急情况。
  • poweroff.targetreboot.targethalt.target: 这些 targets 分别用于关闭、重启或挂起系统。激活时,它们会停止大多数服务并为系统准备所需的电源状态。

管理 Systemd Targets

与 systemd targets 的交互主要涉及 systemctl 命令行工具。

查看活动和默认 Targets

要查看系统当前运行的目标:

systemctl get-default

列出所有当前加载的目标 unit:

systemctl list-units --type=target

此命令显示活动、加载和静态 targets 及其描述。

更改默认启动 Target

您可以更改系统默认启动的目标。例如,将 multi-user.target 设置为默认值:

sudo systemctl set-default multi-user.target

恢复到 graphical.target

sudo systemctl set-default graphical.target

此命令从 /etc/systemd/system/default.target 创建一个指向所需 target 文件的符号链接。

临时启动到不同的 Target

有时您只需要启动到一个特定的 target 一次(例如,用于故障排除)。您可以通过在启动时附加内核参数来实现。当 GRUB 启动菜单出现时,编辑启动项(通常按 e 键),然后在内核命令行中添加 systemd.unit=target_name.target

例如,要启动到救援模式:

systemd.unit=rescue.target

在运行时切换 Targets

您可以使用 systemctl isolate 命令在系统运行时切换到不同的 target。此命令将停止新 target 所需的所有服务,并启动新 target 所需的所有服务。

警告: 使用 systemctl isolate 可能会中断您的系统运行,特别是如果您从桌面计算机上的 graphical.target 切换到像 multi-user.target 这样的低级别 target。请谨慎使用。

graphical.target 切换到 multi-user.target

sudo systemctl isolate multi-user.target

返回到 graphical.target(假设它是之前的状态):

sudo systemctl isolate graphical.target

创建自定义 Targets

虽然 systemd 提供了许多有用的 targets,但您可能会发现创建自定义 target 有益的情况。这对于复杂的应用程序部署尤其如此,您需要将一组应始终一起启动和停止的服务进行分组,或为您的应用程序定义特定的环境。

创建自定义 target:

  1. 创建 .target 文件: 将其放在 /etc/systemd/system/ 中。例如,my-application.target
    ini # /etc/systemd/system/my-application.target [Unit] Description=My Custom Application Target Wants=my-database.service my-webserver.service After=my-database.service my-webserver.service
    • Description: 可读的描述。
    • Wants=: 列出此 target 应引入的服务或其他 targets。
    • After=: 定义顺序。Target 将在这些 unit 启动后启动。
  2. 创建服务: 确保 my-database.servicemy-webserver.service(或您列出的任何服务)存在且配置正确。
  3. 重新加载 systemd: 通知 systemd 新的 unit 文件。
    bash sudo systemctl daemon-reload
  4. 启用和启动: 您现在可以启用和启动自定义 target,它将依次启动其所需的 ist services。
    bash sudo systemctl enable my-application.target sudo systemctl start my-application.target

这允许您将一组相关服务作为一个逻辑单元进行管理,从而简化复杂的应用程序部署。

使用 Targets 进行故障排除

Targets 在排除启动问题或服务故障方面也很有价值:

  • 识别依赖关系: 如果服务启动失败,检查它所属的 target 可以揭示丢失或失败的依赖关系。使用 systemctl status <service_name>systemctl list-dependencies <target_name>
  • 启动到最小 targets: 如果您的系统无法启动到 graphical.targetmulti-user.target,请尝试使用内核参数方法启动到 rescue.targetemergency.target。这提供了一个最小的环境,您可以在其中诊断问题,而无需处理许多运行服务的复杂性。
  • 检查日志: 尝试启动 target 或服务后,始终检查 journalctl 日志以获取错误:
    bash journalctl -b -u <target_or_service_name>

最佳实践和技巧

  • 优先使用 network-online.target: 如果您的服务需要主动的网络连接(例如,访问外部 API),请确保它 After=network-online.target 而不仅仅是 network.target 或特定的网络服务。这使得您的服务在不同的网络设置时间内更具健壮性。
  • 理解启动顺序: 熟悉从 sysinit.targetbasic.target,然后到 multi-user.target/graphical.target 的一般流程。这有助于调试在启动过程早期失败的服务。
  • 谨慎更改 default.target: 更改 default.target 可能会显著改变系统的启动行为。始终先在非生产环境中测试自定义配置。
  • 对非关键依赖项使用 Wants=: 对于对 target 被视为“up”不是严格必需但有用的服务,请使用 Wants= 而不是 Requires=。这可以防止单个可选服务失败导致整个 target 激活失败。

结论

Systemd targets 是现代 Linux 系统管理的核心,它们提供了一种灵活而强大的机制来定义、控制和协调系统状态。通过理解 targets 如何组织 unit、管理依赖项以及定义启动过程,管理员和开发人员可以对系统的行为获得显著的控制。从 multi-user.target 等常见 targets 到自定义应用程序特定的 targets,掌握这些概念对于有效的系统管理、故障排除以及构建健壮、可维护的 Linux 环境至关重要。

在您继续使用 systemd 的旅程中,请记住 targets 是您导航 unit 依赖和系统初始化复杂领域的地图,确保您的服务能够可预测地启动,并且您的系统能够达到预期的运行状态。