57·进程管理进阶

systemd 体系入门

systemdinit

第 57 课 - systemd 体系入门

学习目标

完成本课学习后,你将能够:

  1. 理解 systemd 在现代 Linux 系统中的核心地位和主要作用。
  2. 掌握 systemctl 的基础命令,用于查询和控制系统服务。
  3. 了解 .service 单元文件的基本结构和常见配置项。
  4. 区分 systemd target 与传统的 SysV runlevel 的概念。
  5. 能够使用 journalctl 查看系统和服务日志。

核心概念

1. 什么是 systemd?

想象你的 Linux 系统启动后,需要加载内核、挂载文件系统、启动网络、运行各种服务(如 sshd, nginx, crond)。谁来负责按顺序启动并管理这些任务呢?在传统系统中是 /sbin/init,而现在,绝大多数主流 Linux 发行版(如 Ubuntu 16.04+, CentOS 7+, Fedora, Debian 8+)都使用 systemd 来扮演这个“大管家”的角色。

systemd 是系统的第一个进程(PID 1),它负责在系统启动时激活系统资源、服务器守护进程和其他进程,同时也负责在系统运行期间管理它们。

2. 核心概念:单元(Unit)

systemd 不再用单独的脚本来管理服务,而是引入了一个统一的配置文件概念——单元(Unit)。一个单元通常对应一个“资源”,systemd 通过单元文件来定义如何管理和控制这个资源。

最常见的单元类型是 .service,它描述了一个由 systemd 管理的服务进程。其他类型还有 .socket(套接字)、.target(一组单元的集合)、.mount(文件系统挂载点)等。

单元文件主要存放在:

  • /usr/lib/systemd/system/: 系统安装的软件包提供的原始单元文件(请勿直接修改)。
  • /etc/systemd/system/: 系统管理员自定义的配置或覆盖文件(优先级最高,推荐在此修改)。
  • /run/systemd/system/: 运行时生成的单元文件,重启后失效。

3. 目标(Target)

目标(Target)是一种特殊的单元,它用于将其他单元(通常是 .service)组合在一起,形成一个有意义的系统状态。你可以把它理解为传统 SysV init 系统中“运行级别(runlevel)”的升级版。

  • multi-user.target: 类似于传统的运行级别 3,多用户文本模式。
  • graphical.target: 类似于传统的运行级别 5,图形界面模式。
  • rescue.targetemergency.target: 用于系统救援。

与 runlevel 的线性关系不同,target 之间可以存在依赖关系,并且一个服务可以属于多个 target。

代码示例

1. 使用 systemctl 查询系统和服务状态

# 1. 查看 systemd 自身的状态
systemctl status

# 2. 列出所有活动的(正在运行的)单元
systemctl list-units

# 3. 查看特定服务的状态(以 sshd 为例)
# 输出会清晰显示服务是否正在运行、主进程ID、日志最新几行等信息
systemctl status sshd.service

# 4. 检查某个服务是否设置为开机自启
systemctl is-enabled sshd.service

2. 管理服务:启动、停止、重启、重载

# 启动一个服务(如 httpd)
sudo systemctl start httpd.service

# 停止一个服务
sudo systemctl stop httpd.service

# 重启一个服务(先停止,再启动)
sudo systemctl restart httpd.service

# 重载服务的配置文件(如果服务支持),不中断服务进程
sudo systemctl reload httpd.service

# 启用服务,使其开机自启
sudo systemctl enable httpd.service

# 禁用服务的开机自启
sudo systemctl disable httpd.service

# 一步到位:启动服务并设置开机自启
sudo systemctl enable --now httpd.service

3. 查看单元文件内容

# 查看 sshd 服务的单元文件内容
systemctl cat sshd.service

输出通常会包含类似这样的关键部分:

[Unit]
Description=OpenSSH server daemon
After=network.target sshd-keygen.service

[Service]
Type=notify
EnvironmentFile=-/etc/sysconfig/sshd
ExecStart=/usr/sbin/sshd -D $OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure

[Install]
WantedBy=multi-user.target
  • [Unit]: 描述服务、定义与其他单元的依赖关系(After)。
  • [Service]: 定义服务的启动命令(ExecStart)、停止方式、重启策略等。
  • [Install]: 定义服务被 enable 时应链接到哪个 target(WantedBy)。

4. 查看和切换目标(Target)

# 查看当前系统默认的(下次启动时生效的)目标
systemctl get-default

# 查看当前正在运行的目标
systemctl list-units --type=target

# 切换系统到命令行多用户模式(相当于 init 3)
sudo systemctl isolate multi-user.target

# 修改系统默认启动目标为图形界面(相当于 init 5)
sudo systemctl set-default graphical.target

5. 使用 journalctl 查看日志

# 查看系统启动以来的全部日志(可能很长)
journalctl

# 实时滚动查看最新日志(类似 `tail -f /var/log/messages`)
journalctl -f

# 查看特定服务(如 nginx)的日志
journalctl -u nginx.service

# 查看最近 1 小时内 nginx 服务的日志
journalctl -u nginx.service --since "1 hour ago"

实践练习

练习 1:基础状态查询

  1. 你的系统是否正在运行 sshd 服务?它是否设置为开机自启?
  2. 列出所有当前处于 failed(失败)状态的单元。
    • 提示: 使用 systemctl list-units --state=failed

练习 2:服务单元文件分析

  1. 使用 systemctl cat cron.service 查看 cron 守护进程的单元文件。
  2. 回答以下问题: a. 该服务在哪个网络目标之后启动?(查看 [Unit] 部分的 After) b. 服务的主启动命令是什么?(查看 [Service] 部分的 ExecStart) c. 该服务希望被链接到哪个 target 下实现开机自启?(查看 [Install] 部分的 WantedBy

练习 3:日志分析

  1. 假设你的 nginx 服务无法启动。请使用 journalctl 查看其最近 20 分钟的详细日志,寻找错误原因。
    • 提示journalctl -u nginx.service --since "20 min ago"

常见错误

  1. 混淆 enable/startdisable/stopenable/disable 控制的是下次启动时是否自动运行,不影响当前状态。start/stop 只控制当前的运行状态。要立即改变并影响未来,通常需要组合使用:sudo systemctl enable --now service_name

  2. 直接修改 /usr/lib/systemd/system/ 下的文件: 软件包更新时,这些文件可能会被覆盖。正确的做法是复制到 /etc/systemd/system/ 下进行修改,或者创建一个同名的 .d/*.conf 配置文件来覆盖部分设置。

  3. 不理解服务依赖: 启动一个服务前,systemd 会自动启动其声明依赖(Requires, After)的服务。如果你的自定义服务启动失败,检查日志中是否有依赖服务未就绪的提示。

  4. 误用 systemctl isolateisolate 命令会停止当前 target 中所有不属于新 target 的单元。这是一个影响范围较大的操作,请谨慎使用,主要用于切换运行模式。

小结

本课我们揭开了 systemd 的面纱,掌握了以下关键点:

  • systemd 是现代 Linux 的初始化系统和进程管理器,是 PID 1 进程。
  • 单元(Unit)是配置的基本单位.service 文件定义了如何管理一个服务进程。
  • systemctl 是与 systemd 交互的核心命令,用于查询状态、启停服务、管理开机自启。
  • 目标(Target)是单元的集合,用于组织系统状态,取代了旧的运行级别概念。
  • journalctl 统一管理了系统和所有服务的日志,是排查问题的强力工具。
  • 最佳实践是优先通过 /etc/systemd/system/.d/*.conf 文件来自定义单元配置。

掌握了这些基础,你就为深入学习 systemctl 的更高级用法和编写自定义服务单元文件打下了坚实的基础。下一课,我们将更详细地探讨 systemctl 服务管理的各种技巧。

练习编辑器

rust
Loading...

继续学习

完成本课后,建议继续学习下一课「systemctl 服务管理」 以巩固所学知识。