第 8/30 天
引言
当你运行 systemctl status sshd 查看 SSH 服务状态,或执行 systemctl enable nginx 让 Nginx 开机自启时,你已经在使用 systemd——当今几乎所有主流 Linux 发行版(包括 Ubuntu)的默认初始化系统(init system)。systemd 不仅是进程管理器,更是一个完整的系统和服务管理器,掌管着从开机引导到服务监督、日志收集、定时任务、设备管理、网络配置等方方面面。
今天我们将深入 systemd 的世界,从核心概念到日常运维命令,再到调试排错和自定义服务编写,帮助你真正掌握这套现代 Linux 的「操作系统内核框架」。
核心概念
什么是 systemd?
systemd(System Daemon)是 Linux 系统的初始化系统和服务管理器,由 Lennart Poettering 于 2010 年创建,旨在替代传统的 SysV init 和 Upstart。它的核心特点:
- 并行启动:最大化利用多核 CPU,同时启动不依赖的服务,大幅缩短开机时间
- 依赖管理:通过 Unit 之间的依赖关系,按需自动启动相关服务
- 统一管理:服务、挂载、设备、套接字、定时器……都用同一套语法和工具管理
- CGroup 资源隔离:每个服务运行在独立的 Control Group 中,资源使用可追踪可限制
- Socket 激活:服务无需开机启动,只有收到请求时自动按需拉起
核心概念:Unit
在 systemd 中,一切管理对象都被抽象为 Unit(单元)。每个 Unit 对应一个配置文件(.service、.timer、.mount 等),定义了该资源的启动方式、依赖关系、执行命令等。
| Unit 类型 | 扩展名 | 用途 | 示例 |
|---|---|---|---|
| 服务单元 | .service |
管理后台服务进程 | ssh.service, nginx.service |
| 套接字单元 | .socket |
管理网络或 IPC 套接字 | docker.socket |
| 设备单元 | .device |
管理内核设备 | sys-subsystem-net-devices-eth0.device |
| 挂载单元 | .mount |
管理文件系统挂载点 | home.mount |
| 自动挂载单元 | .automount |
按需自动挂载 | mnt-data.automount |
| 定时器单元 | .timer |
替代 cron 的定时任务 | systemd-tmpfiles-clean.timer |
| 路径单元 | .path |
监控文件路径变化 | 自定义日志监控 |
| 目标单元 | .target |
逻辑分组,类似 SysV 的运行级别 | multi-user.target, graphical.target |
Unit 配置文件层级
/etc/systemd/system/ # 系统管理员定义(优先级最高)
/run/systemd/system/ # 运行时定义(重启后消失)
/lib/systemd/system/ # 发行版默认定义(apt 安装的软件包写在这里)
Ubuntu 的原则:不要修改 /lib/systemd/system/ 下的文件。自定义或覆盖配置应放在 /etc/systemd/system/ 下。
实战步骤
步骤一:服务状态查询
# 查看所有 Unit 状态(包括运行中、失败、退出的)
systemctl list-units
# 仅查看服务类 Unit
systemctl list-units --type=service
# 查看所有已加载的 Unit(包括 inactive 的)
systemctl list-units --all
# 查看所有已安装的 Unit 文件(含未加载的)
systemctl list-unit-files
# 查看失败的服务
systemctl --failed
输出示例:
UNIT LOAD ACTIVE SUB DESCRIPTION
cron.service loaded active running Regular background program processing daemon
nginx.service loaded active running A high performance web server
ssh.service loaded active running OpenBSD Secure Shell server
systemd-journald.service loaded active running Journal Service
systemd-logind.service loaded active running Login Service
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
步骤二:服务生命周期管理
# 启动服务
sudo systemctl start nginx
# 停止服务
sudo systemctl stop nginx
# 重启服务
sudo systemctl restart nginx
# 重新加载配置(不中断服务)
sudo systemctl reload nginx
# 如果服务支持 reload 但不确定,用 reload-or-restart
sudo systemctl reload-or-restart nginx
# 查看详细状态
sudo systemctl status nginx
systemctl status 的输出非常丰富:
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2026-07-21 10:00:00 CST; 2h 30min ago
Docs: man:nginx(8)
Process: 1234 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Process: 1235 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Main PID: 1236 (nginx)
Tasks: 2 (limit: 2317)
Memory: 5.2M
CPU: 123ms
CGroup: /system.slice/nginx.service
├─1236 nginx: master process /usr/sbin/nginx -g daemon on; master_process on
└─1237 nginx: worker process
关键信息含义:
– Loaded:配置文件是否已加载以及是否开机自启(enabled/disabled)
– Active:服务当前运行状态(active/running, inactive/dead, failed)
– Main PID:主进程 PID
– Tasks:该服务使用的任务数
– CGroup:CGroups 层级,显示所有子进程
步骤三:开机自启管理
# 启用开机自启
sudo systemctl enable nginx
# 禁用开机自启
sudo systemctl disable nginx
# 启用并立即启动(常用组合)
sudo systemctl enable --now nginx
# 禁用并立即停止
sudo systemctl disable --now nginx
# 检查是否开机自启
systemctl is-enabled nginx
# 查看所有已启用的服务
systemctl list-unit-files --state=enabled
步骤四:日志查看(journalctl)
systemd 自带日志系统 journald,统一管理所有服务的日志输出。
# 查看所有日志(最新在末尾)
journalctl
# 查看特定服务的日志
journalctl -u nginx.service
# 查看最近 30 分钟的日志
journalctl --since "30 min ago"
# 查看今天的日志
journalctl --since today
# 查看特定时间范围的日志
journalctl --since "2026-07-21 08:00:00" --until "2026-07-21 10:00:00"
# 实时跟踪日志(类似 tail -f)
journalctl -u nginx.service -f
# 查看内核日志
journalctl -k
# 查看错误级别以上的日志
journalctl -p err
# 查看最近 N 条日志
journalctl -n 50
# 以 JSON 格式输出(便于程序解析)
journalctl -u nginx.service -o json-pretty
步骤五:分析系统启动时间
# 查看总体启动耗时
systemd-analyze
# 查看每个服务的启动耗时(按时间排序)
systemd-analyze blame
# 查看关键事件链
systemd-analyze critical-chain
# 生成 SVG 启动时间图(可直观分析)
systemd-analyze plot > /tmp/boot.svg
systemd-analyze blame 输出示例:
3.214s networkd-dispatcher.service
2.896s udisks2.service
2.214s snapd.service
1.843s dev-sda1.device
1.567s systemd-resolved.service
1.234s NetworkManager-wait-online.service
0.987s postgresql@14-main.service
步骤六:编写自定义 systemd 服务
假设你有一个 Python 应用 ~/app/server.py,希望它作为系统服务运行。
1. 创建服务配置文件:
sudo tee /etc/systemd/system/myapp.service << 'EOF'
[Unit]
Description=My Custom Python Application
Documentation=https://example.com/docs
After=network.target postgresql.service
Wants=postgresql.service
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/python3 /opt/myapp/server.py
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
TimeoutStopSec=30
Environment="PYTHONUNBUFFERED=1"
EnvironmentFile=/opt/myapp/.env
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
关键参数说明:
| 参数 | 说明 | 推荐值 |
|---|---|---|
Type |
服务类型(simple/forking/oneshot/notify/dbus) | 普通服务用 simple |
User/Group |
运行服务的用户 | 遵循最小权限原则 |
ExecStart |
启动命令(绝对路径) | 始终使用完整路径 |
Restart |
重启策略(no/on-failure/on-abnormal/always) | on-failure 最实用 |
RestartSec |
重启间隔(秒) | 5-10 秒 |
EnvironmentFile |
环境变量文件 | 避免机密信息写在配置中 |
LimitNOFILE |
文件描述符限制 | 高并发服务设为 65536 |
2. 重新加载 systemd 配置:
sudo systemctl daemon-reload
3. 启用并启动服务:
sudo systemctl enable --now myapp
4. 查看运行状态:
sudo systemctl status myapp
步骤七:使用 systemd Timer 替代 cron
systemd timer 比 cron 更强大:支持随机延迟、跳过已错过的任务、依赖其他服务、日志统一管理。
示例:每天凌晨 3 点执行备份脚本
1. 创建服务单元(timer 触发的工作):
sudo tee /etc/systemd/system/backup.service << 'EOF'
[Unit]
Description=Daily Backup Script
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
User=root
EOF
2. 创建定时器单元:
sudo tee /etc/systemd/system/backup.timer << 'EOF'
[Unit]
Description=Run backup daily at 3 AM
Requires=backup.service
[Timer]
OnCalendar=daily
OnCalendar=*-*-* 03:00:00
RandomizedDelaySec=300
Persistent=true
[Install]
WantedBy=timers.target
EOF
参数说明:
– OnCalendar=daily:每天执行一次
– OnCalendar=*-*-* 03:00:00:指定每天凌晨 3 点
– RandomizedDelaySec=300:随机延迟 0-300 秒,避免所有定时器同时触发
– Persistent=true:如果系统在预定时间关机,开机后补执行
3. 启用定时器:
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
4. 查看所有定时器:
systemctl list-timers --all
输出示例:
NEXT LEFT LAST PASSED UNIT ACTIVATES
Tue 2026-07-22 00:00:00 CST 13h left Tue 2026-07-21 00:00:12 CST 10h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
Tue 2026-07-22 03:00:00 CST 16h left n/a n/a backup.timer backup.service
步骤八:Mask 和覆盖
有时需要屏蔽某些服务,使其完全无法启动:
# 屏蔽服务(创建指向 /dev/null 的符号链接)
sudo systemctl mask apt-daily.service
# 解除屏蔽
sudo systemctl unmask apt-daily.service
# 覆盖服务配置(不修改原始文件)
sudo systemctl edit nginx.service
# 这会创建 /etc/systemd/system/nginx.service.d/override.conf
覆盖配置示例:
[Service]
# 增加 nginx 的文件描述符限制
LimitNOFILE=65536
# 覆盖 ExecStart 前的清理操作
ExecStartPre=
ExecStartPre=/usr/bin/sleep 10
常见问题
Q1: 修改了服务配置后为什么不生效?
现象:编辑了 /lib/systemd/system/nginx.service 后重启服务,配置没变。
原因:systemd 缓存了配置,需要重新加载。
解决方案:
# 编辑配置后必须执行
sudo systemctl daemon-reload
# 然后重启服务
sudo systemctl restart nginx
Q2: 服务启动失败,但日志没有明确错误
现象:systemctl start myservice 返回失败,status 只显示 failed。
解决方案:使用 journalctl 查看详细日志:
# 查看该服务的完整日志
journalctl -u myservice.service -n 100 --no-pager
# 查看实时日志后启动服务
journalctl -u myservice.service -f &
systemctl start myservice
Q3: 服务无法停止(卡在 stop 状态)
现象:systemctl stop myservice 超时,服务一直显示 deactivating。
解决方案:
# 查看还在运行的进程
systemctl status myservice
# 强制终止(发送 SIGKILL)
sudo systemctl kill -s SIGKILL myservice
# 或设置超时后强制结束
sudo systemctl stop myservice --force
防止未来出现此问题,修改服务配置:
[Service]
TimeoutStopSec=30
KillMode=mixed
Q4: systemd 版本差异
现象:Ubuntu 20.04 和 22.04 的 systemd 命令行为不同。
原因:Ubuntu 20.04 使用 systemd 245,22.04 使用 249,功能有差异。
| 功能 | 20.04 (v245) | 22.04 (v249) |
|---|---|---|
systemctl --user |
支持 | 支持,更完善 |
systemd-resolve → resolvectl |
旧命令 | 新命令 |
oomd |
不支持 | 支持 |
systemd-sysusers |
不支持 | 支持 |
检查版本:
systemd --version
Q5: 服务启动顺序依赖
现象:服务 A 需要数据库就绪后才能启动,但有时 A 先启动导致连接失败。
解决方案:使用 After + Wants 组合,再加上重试机制:
[Unit]
Description=My App
After=network.target postgresql.service
Wants=postgresql.service
[Service]
Type=simple
# 使用脚本等待数据库就绪
ExecStartPre=/usr/local/bin/wait-for-it.sh localhost:5432 --timeout=30
ExecStart=/usr/bin/python3 /opt/myapp/server.py
Restart=on-failure
RestartSec=5
总结
-
systemd 是现代 Linux 的核心 — 它不仅是 init 系统,更是统一的服务管理器、日志系统、定时任务系统。掌握 systemd 是 Ubuntu 运维的必修课。
-
核心命令三板斧:
systemctl(服务管理)、journalctl(日志查看)、systemd-analyze(性能分析),覆盖了从日常运维到故障排查的完整场景。 -
自定义服务最佳实践:使用
Type=simple+Restart=on-failure+RestartSec=5作为通用模板;通过daemon-reload使配置生效;用systemctl edit覆盖而非直接修改原始文件。 -
Timer 比 cron 更强大:随机延迟、持久化执行、统一日志管理的优势让它成为现代 Linux 的首选定时方案。
-
排错思路:先
status看状态,再journalctl -u查日志,然后daemon-reload排除缓存问题,最后analyze blame定位性能瓶颈。
下期预告
第 9 天我们将探讨磁盘与文件系统管理——从 lsblk 和 fdisk 分区工具,到 mkfs 创建文件系统、mount 挂载管理,再到 LVM 逻辑卷的弹性伸缩实战,带你全面掌握 Ubuntu 存储管理。
系列目录
| 天数 | 主题 | 链接 |
|---|---|---|
| 第 1 天 | Ubuntu 简介与版本选择 | 阅读 |
| 第 2 天 | 手把手安装 Ubuntu | 阅读 |
| 第 3 天 | Ubuntu 桌面环境初探 | 阅读 |
| 第 4 天 | Ubuntu 终端基础 | 阅读 |
| 第 5 天 | 用户与权限管理 | 阅读 |
| 第 6 天 | 软件包管理 | 阅读 |
| 第 7 天 | 文件与文本操作 | 阅读 |
| 第 8 天 | 系统服务管理:systemd 与 systemctl | ← 今日发布 |
| 第 9 天 | 磁盘与文件系统管理 | 🔜 敬请期待 |















暂无评论内容