Systemd和Systemctl的关系及相关理解
2026-06-06
运维
00

目录

1. 从 SysVinit 到 Systemd:一次静默的系统管理变革
2. systemd 的核心概念:单元(Unit)体系
3. systemctl:管理员的核心操作接口
3.1 服务生命周期管理
3.2 开启自启与状态查询
3.3 单元管理进阶操作
3.4 系统运行目标的切换
3.5 系统电源管理
4. 编写自定义 Service 文件
4.1 基本模板
4.2 段落详解
[Unit] 段落
[Service] 段落
[Install] 段落
4.3 部署步骤
5. 配套工具:构建完整的 systemd 工具链
5.1 journalctl:集中式日志管理
5.2 hostnamectl:主机名管理
5.3 timedatectl:时间、日期、时区控制
5.4 其他实用工具
6. 最佳实践与故障排查思路
6.1 服务文件编写建议
6.2 常见问题排查方法
7. 结语

1. 从 SysVinit 到 Systemd:一次静默的系统管理变革

在当前的 Linux 发行版中,绝大多数(如 CentOS 7 及以上、Ubuntu 16.04 及以上、Debian 8 及以上、Fedora、Arch Linux 等)都已将 systemd 作为标准的初始化系统和服务管理器。在此之前的很长一段时间里,Linux 系统普遍采用 SysVinit 或 Upstart 来启动和管理服务,它们通常通过 /etc/init.d/ 下的脚本或 service 命令进行操作。

systemd 的设计目标是克服传统初始化系统的诸多局限,例如串行启动速度慢、脚本维护复杂、服务依赖管理不够清晰等问题。如今,理解 systemd 已经成为现代 Linux 运维的必备技能。不过,很多初学者容易混淆 systemdsystemctl 这两个概念,下面先做一个明确的区分:

  • systemd:系统守护进程,PID=1,即 Linux 内核启动后运行的第一个用户态进程。它常驻后台,负责整个系统的启动、服务管理、进程监控、设备挂载、定时任务、日志收集以及电源管理等一系列核心功能。
  • systemctl:管理员用来与 systemd 进行交互的命令行工具。无论是启停服务、设置开机自启,还是查看状态、分析依赖,都通过 systemctl 命令完成。

简单地说,systemd 是管理者,systemctl 是管理工具。本文将系统介绍 systemd 的单元(Unit)体系、systemctl 的日常使用、自定义服务文件的编写,以及配套的日志、时间、主机名管理工具,帮助读者建立起完整的知识框架。

2. systemd 的核心概念:单元(Unit)体系

systemd 将系统中一切可管理的资源抽象为 Unit(单元),并采用统一的方式对其进行配置与监控。这种设计的好处是,无论是要管理一个后台服务、一个挂载点,还是一个定时任务,都可以用相同的语法和命令来操作。

每个 Unit 通过文件后缀来区分类型,常见的单元类型如下表所示:

后缀单元类型用途说明
.service服务单元最常用的类型,用于定义后台守护进程,如 nginx、mysql、sshd 等。
.socket套接字单元监听网络套接字或 IPC 通道,可配合 service 实现按需启动。
.mount挂载单元管理系统挂载点,可代替传统的 /etc/fstab 配置。
.automount自动挂载单元当某个目录被访问时自动触发挂载操作,常用于网络文件系统。
.target目标单元用于分组管理其他单元,相当于传统运行级别的概念(如 multi-user.target)。
.device设备单元由 udev 根据内核检测到的硬件设备动态创建。
.swap交换分区单元管理 swap 分区或 swap 文件。
.timer定时器单元定义基于时间或事件的任务触发,可替代传统的 cron 任务。
.path路径监控单元监控文件或目录的变化,一旦事件发生便启动关联的服务。

这些单元的定义文件主要存放在两个目录:

  • /usr/lib/systemd/system/:系统自带的单元文件,由发行版包管理器维护。
  • /etc/systemd/system/:管理员自定义的单元文件,具有更高优先级,可以覆盖系统默认配置。

当使用 systemctl enable 命令时,实际上是在 /etc/systemd/system/ 的对应 target 目录下创建符号链接,从而实现开机自启。

3. systemctl:管理员的核心操作接口

systemctl 是操作 systemd 单元的统一命令,其基本用法为:

展开代码
systemctl [选项] 动作 [单元名称...]

下面按照典型的运维场景,分类列出常用命令。

3.1 服务生命周期管理

展开代码
# 启动服务 systemctl start nginx.service # 停止服务 systemctl stop nginx.service # 重启服务 systemctl restart nginx.service # 重新加载配置(服务必须支持重载操作) systemctl reload nginx.service # 优雅地重新加载或重启(如果服务支持) systemctl try-restart nginx.service # 杀死服务进程(默认发送 SIGTERM,可指定信号) systemctl kill -s SIGKILL nginx.service

提示:当单元类型为 .service 时,命令中的后缀通常可以省略,systemctl start nginx 等价于 systemctl start nginx.service

3.2 开启自启与状态查询

展开代码
# 设置服务开机自动启动 systemctl enable nginx.service # 禁止服务开机自启 systemctl disable nginx.service # 查看服务当前状态(活跃/非活跃、PID、内存占用、最近日志) systemctl status nginx.service # 确认某个服务是否被设为开机启动 systemctl is-enabled nginx.service # 列出所有处于活跃(运行)状态的服务单元 systemctl list-units --type=service --state=running # 列出所有已安装的服务单元文件(无论是否激活) systemctl list-unit-files --type=service # 查看服务的依赖关系树 systemctl list-dependencies nginx.service

3.3 单元管理进阶操作

展开代码
# 重载 systemd 配置,新增或修改了 unit 文件后必须执行 systemctl daemon-reload # 编辑某个现有单元(会自动创建覆盖文件,位于 /etc/systemd/system/ 下) systemctl edit nginx.service # 查看单元的完整配置内容(包括覆盖部分) systemctl cat nginx.service # 显示单元的所有底层属性 systemctl show nginx.service # 屏蔽某个服务(使其无法被手动或自动启动) systemctl mask nginx.service # 取消屏蔽 systemctl unmask nginx.service

mask 命令会将单元文件符号链接至 /dev/null,达到了彻底禁用的效果,常用于防止冲突的服务意外启动。

3.4 系统运行目标的切换

systemd 使用 target 来管理运行级别:

展开代码
# 切换到多用户模式(命令行界面,类似传统的 runlevel 3) systemctl isolate multi-user.target # 切换到图形界面模式(类似传统 runlevel 5) systemctl isolate graphical.target # 设置系统默认启动目标 systemctl set-default multi-user.target # 查看当前设置的默认目标 systemctl get-default

3.5 系统电源管理

展开代码
# 关机 systemctl poweroff # 重启 systemctl reboot # 挂起 systemctl suspend # 休眠 systemctl hibernate

4. 编写自定义 Service 文件

在运维工作中,经常需要将自行开发的程序或第三方软件注册为 systemd 服务,以便统一管理。一个标准的 service 文件由三个段落组成:[Unit][Service][Install]

4.1 基本模板

创建文件 /etc/systemd/system/demo.service,内容如下:

展开代码
ini[Unit] Description=Demo Application Service Documentation=https://docs.example.com After=network.target remote-fs.target Wants=network-online.target [Service] Type=simple User=appuser Group=appuser WorkingDirectory=/opt/demo ExecStart=/usr/bin/python3 /opt/demo/app.py --port=8080 ExecStop=/bin/kill -s QUIT $MAINPID Restart=on-failure RestartSec=5s Environment="APP_ENV=production" LimitNOFILE=65536 PrivateTmp=true [Install] WantedBy=multi-user.target

4.2 段落详解

[Unit] 段落

  • Description:对服务的简要描述,会显示在 systemctl status 中。
  • Documentation:可选的参考文档地址。
  • After:定义启动顺序,表示本服务应在所列单元启动之后再启动,但不构成强依赖。
  • Before:与 After 相反,声明本服务应在所列单元启动之前启动。
  • Wants:弱依赖关系。期望所列单元启动,但如果它们启动失败,不会导致本服务失败。
  • Requires:强依赖关系。如果任一所需单元启动失败,本服务也将被停止。
  • BindsTo:比 Requires 更紧密的绑定,如果所绑定的单元停止,本服务也会被立刻停止。

[Service] 段落

  • Type:启动类型,直接影响 systemd 如何判断服务是否启动成功。

    • simple(默认):ExecStart 启动的进程即为服务的主进程,意味着 systemd 会立即认为服务已经启动。
    • forking:服务自身调用 fork() 后父进程退出,子进程成为守护进程。此时通常需要配合 PIDFile 指定 PID 文件路径。
    • oneshot:执行一次任务即退出,通常需要结合 RemainAfterExit=yes 以便 systemd 认为该服务仍然处于“活跃”状态。
    • notify:服务在启动完成后会通过 sd_notify 发送通知,systemd 收到通知后才会认为服务启动完成。
    • idle:类似 simple,但会等待所有任务(jobs)分派完毕后才启动服务。
  • ExecStart:必填项,定义启动服务时所执行的命令及其参数。

  • ExecStop:自定义停止命令。若不指定,systemd 会先发送 SIGTERM,等待超时后发送 SIGKILL

  • ExecReload:自定义重载配置命令(配合 systemctl reload 使用)。

  • Restart:退出后重启策略。

    • no(默认):不自动重启。
    • always:无论退出码如何,都重启。
    • on-success:仅当退出码为 0 时重启。
    • on-failure:当退出码非 0 或进程被信号终止时重启。
  • RestartSec:重启前的等待时间,默认 100ms,可设为 5s1min 等。

  • User / Group:指定服务运行时的用户和组,强烈建议不要使用 root 运行服务。

  • WorkingDirectory:服务的工作目录。

  • Environment:设置环境变量,可多次使用。

  • LimitNOFILE:限制打开文件描述符的最大数量。

  • PrivateTmp:设为 true 将给服务分配独立的 /tmp 目录,增强安全性。

[Install] 段落

  • WantedBy:指定在哪个 target 下启用该服务。绝大多数系统服务都填写 multi-user.target,表示在多用户命令行模式下自动启动。
  • RequiredBy:与 WantedBy 类似但创建强依赖链接。

4.3 部署步骤

  1. 将编写好的 .service 文件放置到 /etc/systemd/system/ 目录下。
  2. 执行 systemctl daemon-reload 重载 systemd 配置。
  3. 启动服务:systemctl start demo.service
  4. 检查状态:systemctl status demo.service
  5. 若希望开机自动启动,执行 systemctl enable demo.service

修改 unit 文件后,也需要执行 systemctl daemon-reload 才能生效。

关于自定义 Service 服务的使用,可以参考我另外的一篇博客,这篇博客中就是封装了自定义服务。

5. 配套工具:构建完整的 systemd 工具链

systemd 提供了一系列与系统管理相关的命令行工具,它们都以 ctl 结尾,与 systemctl 风格一致,易学易用。

5.1 journalctl:集中式日志管理

在 systemd 的架构中,所有由服务输出的标准输出、标准错误以及 syslog 消息,都被收集到统一的二进制日志系统(journal)中。journalctl 是用来访问和筛选这些日志的工具。

展开代码
# 查看全部日志(默认从最新的条目开始) journalctl # 查看某个服务的所有日志 journalctl -u nginx.service # 实时跟踪日志(类似 tail -f) journalctl -fu nginx.service # 按时间范围过滤 journalctl --since "2025-06-01" --until "2025-06-02" journalctl --since "1 hour ago" # 只显示错误或更严重的日志(级别 err 及以下) journalctl -p err # 查看本次系统启动以来的日志 journalctl -b # 查看上一次启动的日志(在排查崩溃问题时非常有用) journalctl -b -1 # 按用户 ID、可执行文件路径等高级条件过滤 journalctl _UID=1000 journalctl _EXE=/usr/bin/sshd

默认情况下,journal 日志存储在内存中,重启后会丢失。若需持久化存储,应修改 /etc/systemd/journald.conf

展开代码
Storage=persistent

然后重启日志服务:systemctl restart systemd-journald。持久化日志会保存在 /var/log/journal/ 目录下。

5.2 hostnamectl:主机名管理

展开代码
# 查看当前主机名及相关信息(静态主机名、操作系统、内核等) hostnamectl # 设置系统主机名(同时更新静态、瞬态和美观名称) hostnamectl set-hostname new-hostname # 单独设置美观主机名(可包含空格和特殊字符) hostnamectl set-hostname "Production Web Server" --pretty

该工具实际上修改的是 /etc/hostname 文件以及内核的瞬态主机名。

5.3 timedatectl:时间、日期、时区控制

展开代码
# 查看当前系统时间、硬件时钟、时区和 NTP 同步状态 timedatectl # 列出所有可用时区 timedatectl list-timezones # 设置时区(例如中国标准时间) timedatectl set-timezone Asia/Shanghai # 启用或禁用网络时间同步(通常需要配合 chrony 或 systemd-timesyncd) timedatectl set-ntp true # 手动设置日期和时间(需要先关闭 NTP 同步) timedatectl set-time "2026-12-31 23:59:59"

5.4 其他实用工具

  • systemd-analyze:启动性能分析工具。

    展开代码
    # 查看本次启动总耗时 systemd-analyze # 按耗时排序,列出每个服务的启动时间 systemd-analyze blame # 显示启动过程的关键路径(最长耗时链) systemd-analyze critical-chain
  • loginctl:管理用户登录会话、座位等。

  • systemd-cgls / systemd-cgtop:查看 cgroup 层级结构及实时资源使用情况。

6. 最佳实践与故障排查思路

6.1 服务文件编写建议

  • 最小权限原则:通过 User=Group= 为服务指定专用的非特权账户,避免以 root 身份运行。
  • 资源限制:适当配置 LimitNOFILEMemoryMaxCPUQuota 等,防止服务过度消耗系统资源。
  • 安全增强:开启 PrivateTmp=trueProtectSystem=fullNoNewPrivileges=true 等指令,可有效提升隔离性。
  • 明确的启动类型:优先使用 Type=simple,若应用程序本身会 fork 到后台,则选择 Type=forking 并正确指定 PIDFile

6.2 常见问题排查方法

  1. 服务启动失败
    • 执行 systemctl status <服务名>,输出的最后几行通常会给出错误信息。
    • 查看详细日志:journalctl -xe -u <服务名>
    • 检查命令路径、工作目录、环境变量是否正确,用户权限是否足够。
  2. 配置文件修改后未生效
    • 务必运行 systemctl daemon-reload,再重新启动服务。
  3. 开机自启不生效
    • 确认已执行 systemctl enable <服务名>
    • 使用 systemctl is-enabled <服务名> 检查状态。
    • 确认 [Install] 段中的 WantedBy 指向正确的 target。
  4. 依赖顺序异常
    • 使用 systemctl list-dependencies <服务名> 分析依赖树。
    • 确认 After / Before 以及 Requires / Wants 配置是否符合实际需求。
  5. 日志持久化问题
    • 检查 /etc/systemd/journald.conf 中的 Storage 选项,确保已设为 persistent 并重启了 systemd-journald 服务。

7. 结语

Systemd 并非单纯替换了旧的 init 系统,而是构建了一套统一、高效且可扩展的服务管理体系。对于刚步入职场的 Linux 学习者而言,熟练掌握 systemctl 操作、理解 Unit 的编写方法,以及善用 journalctl 等日志排查工具,是运维的必备技能喔。

本文作者:zzz

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!