前言
systemd 是当今绝大多数 Linux 发行版的初始化系统和服务管理器。从 Ubuntu 16.04+、Debian 8+、CentOS 7+ 到 RHEL 8+,systemd 早已取代传统的 SysV init 成为标配。而 systemctl 就是控制 systemd 的核心命令——不懂 systemctl,就等于不会管理 Linux 服务。
本教程将从最基础的 service 启动/停止/重启讲起,逐步深入到服务依赖配置、多服务编排、故障排查和性能优化,帮你一次性吃透 systemctl。
一、基础篇:服务的生命周期管理
1. 查看服务状态
最常用的操作就是查看某个服务是否在运行:
$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2026-05-25 08:30:15 UTC; 2h 15min ago
Docs: man:nginx(8)
Main PID: 12345 (nginx)
Tasks: 2 (limit: 2345)
Memory: 12.3M
CPU: 0.245s
CGroup: /system.slice/nginx.service
├─12345 nginx: master process /usr/sbin/nginx -g daemon off;
└─12346 nginx: worker process
输出信息非常丰富:
- Loaded:服务是否已加载,以及是否设置为开机自启(enabled/disabled)
- Active:当前运行状态,后面带运行时长
- Main PID:主进程ID
- Memory/CPU:资源占用情况
2. 启动、停止与重启服务
# 启动服务
$ sudo systemctl start nginx
# 停止服务
$ sudo systemctl stop nginx
# 重启服务
$ sudo systemctl restart nginx
# 重新加载配置(不中断服务)
$ sudo systemctl reload nginx
restart 会先 stop 再 start,有短暂中断。而 reload 只让服务重新读取配置文件,不会中断正在处理的请求——生产环境优先用 reload。
3. 设置开机自启
# 启用开机自启
$ sudo systemctl enable nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
# 禁用开机自启
$ sudo systemctl disable nginx
Removed "/etc/systemd/system/multi-user.target.wants/nginx.service".
# 查看是否已启用
$ systemctl is-enabled nginx
enabled
# 启用并立即启动(一步到位)
$ sudo systemctl enable --now nginx
enable --now 是实战中最常用的组合拳——设置开机自启的同时立即启动服务,省得敲两遍命令。
二、进阶篇:服务状态查询
4. 列出所有服务
# 列出所有正在运行的服务
$ systemctl list-units --type=service --state=running
# 列出所有服务(包括未运行的)
$ systemctl list-units --type=service --all
# 列出所有已启用的服务
$ systemctl list-unit-files --type=service --state=enabled
# 列出所有启动失败的服务(排查问题专用)
$ systemctl --failed
UNIT LOAD ACTIVE SUB DESCRIPTION
● nginx.service loaded failed failed nginx - high performance web server
systemctl --failed 是服务器日常巡检的黄金命令,一眼找出所有挂掉的服务。
5. 检查服务是否存活
# 检查单个服务是否正在运行(返回码可用于脚本)
$ systemctl is-active nginx
active
# 批量检查
$ for svc in nginx mysql redis; do
echo "$svc: $(systemctl is-active $svc)"
done
nginx: active
mysql: active
redis: inactive
6. 查看服务依赖关系
# 查看某服务依赖了哪些其他单元
$ systemctl list-dependencies nginx
nginx.service
● ├─system.slice
● ├─network.target
● └─basic.target
# 查看哪些服务依赖该服务
$ systemctl list-dependencies --reverse nginx
nginx.service
● └─multi-user.target
依赖关系在排查启动顺序问题时至关重要——比如你的应用需要网络后才启动,而网络服务还没就绪,那应用自然起不来。
三、高级篇:编写自己的服务单元
7. 编写一个 systemd service 文件
假设你有一个 Python Web 应用 /opt/myapp/app.py,想把它注册为系统服务:
$ sudo vim /etc/systemd/system/myapp.service
[Unit]
Description=My Python Web Application
After=network.target
Wants=redis.service
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/python3 /opt/myapp/app.py
Restart=always
RestartSec=5
Environment="PYTHONPATH=/opt/myapp"
Environment="LOG_LEVEL=info"
[Install]
WantedBy=multi-user.target
关键字段解释:
- After:声明本服务在网络就绪后再启动(不是依赖,只是顺序)
- Wants:弱依赖——Redis 启动失败不会阻止本服务启动
- Type=simple:最常见的类型,主进程直接运行在前台
- Restart=always:只要进程退出就自动重启(生产环境必配)
- RestartSec=5:重启前等待5秒,避免频繁重启打满CPU
8. 加载并启动自定义服务
# 重新加载 systemd 配置(每次修改 .service 文件后必须执行)
$ sudo systemctl daemon-reload
# 启动自定义服务
$ sudo systemctl start myapp
# 查看状态
$ systemctl status myapp
# 设置为开机自启
$ sudo systemctl enable myapp
重要: 每次修改 .service 文件,都必须运行 systemctl daemon-reload,否则 systemd 不会感知变更。
9. 几种常见的 Service Type
| Type | 适用场景 | 说明 |
|---|---|---|
| simple | 普通应用、Web服务 | ExecStart 指定的进程就是主进程,一直运行在前台 |
| forking | 传统 daemon 程序(如 Nginx) | 进程 fork 后父进程退出,子进程继续运行;需要配合 PIDFile |
| oneshot | 一次性任务、初始化脚本 | 执行一次就退出,可配合 RemainAfterExit=yes 标记执行成功状态 |
| notify | 支持 sd_notify 的现代应用 | 服务启动完成后主动通知 systemd,更精确的健康检测 |
以 Nginx 为例,它的 service 文件使用了 Type=forking:
$ cat /lib/systemd/system/nginx.service | head -15
[Unit]
Description=A high performance web server and a reverse proxy server
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=/usr/sbin/nginx -g 'daemon on; master_process on;' -s quit
四、生产环境实战:服务编排
10. 多服务依赖启动
假设你有一个 Web 应用依赖 MySQL 和 Redis:
[Unit]
Description=My Web App
Requires=mysql.service redis.service
After=network.target mysql.service redis.service
[Service]
Type=simple
ExecStart=/usr/bin/java -jar /opt/app/app.jar
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
Requires 和 After 的区别:
- Requires:强依赖——如果 MySQL 或 Redis 启动失败,本服务也不会启动
- After:只控制启动顺序,不决定是否启动
两者通常配合使用:Requires 保证依赖存在,After 保证顺序正确。
11. 使用 systemctl 管理定时任务(systemd-timer)
systemd 自带 timer 机制,可以替代 crontab:
# 创建定时器单元
$ sudo vim /etc/systemd/system/backup.service
[Unit]
Description=Daily Database Backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
$ sudo vim /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily at 3am
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
# 启用定时器
$ sudo systemctl enable --now backup.timer
# 查看所有定时器
$ systemctl list-timers
NEXT LEFT LAST PASSED UNIT ACTIVATES
Mon 2026-05-26 03:00:00 UTC 17h left Sun 2026-05-25 03:00:00 UTC 7h ago backup.timer backup.service
12. 日志查看与排错
# 查看服务的完整日志
$ journalctl -u nginx
# 只看最近的20条
$ journalctl -u nginx -n 20
# 实时追踪日志(类似 tail -f)
$ journalctl -u nginx -f
# 查看指定时间段的日志
$ journalctl -u nginx --since "2026-05-25 08:00:00" --until "2026-05-25 09:00:00"
# 只看错误级别以上的日志
$ journalctl -u nginx -p err
# 查看内核日志
$ journalctl -k
13. 屏蔽与掩码服务
# 禁用服务(disable 只是取消开机自启,还可以手动启动)
$ sudo systemctl disable apache2
# 彻底屏蔽服务(连手动启动都不允许)
$ sudo systemctl mask apache2
Created symlink /etc/systemd/system/apache2.service → /dev/null.
# 取消屏蔽
$ sudo systemctl unmask apache2
mask 在安全加固时非常有用——如果某服务存在已知漏洞且暂不修复,直接 mask 掉,彻底杜绝意外启动。
五、性能与调试技巧
14. 分析服务启动耗时
# 查看系统启动总耗时
$ systemd-analyze
Startup finished in 3.245s (kernel) + 12.876s (userspace) = 16.121s
graphical.target reached after 12.876s in userspace
# 查看每个服务启动耗时排行榜
$ systemd-analyze blame
5.234s mysql.service
3.876s networking.service
2.145s systemd-udevd.service
1.234s nginx.service
0.876s redis.service
0.345s ssh.service
# 生成启动时间 SVG 火焰图
$ systemd-analyze plot > boot.svg
服务器启动慢?跑一遍 systemd-analyze blame,一眼锁定最慢的服务,针对性优化。
15. 查看服务的资源占用
# 以类似 top 的方式查看所有服务资源占用
$ systemd-cgtop
Control Group Tasks %CPU Memory Input/s Output/s
/system.slice/mysql.service 12 2.3% 1.2G 0B 0B
/system.slice/nginx.service 6 0.8% 45.3M 0B 0B
/system.slice/redis.service 4 0.1% 12.1M 0B 0B
六、排查指南
常见问题速查
- 服务启动失败但没报错? →
journalctl -xe查看最新系统日志 - 修改了 .service 文件没生效? → 先执行
systemctl daemon-reload - 服务起起停停? → 检查
Restart=设置,可能是程序本身 crash 了 - 开机自启没生效? → 确认
systemctl is-enabled返回 enabled,并且[Install]段有WantedBy=multi-user.target - 端口被占用无法启动? →
ss -tlnp | grep :端口号找谁在用
常见问题(FAQ)
Q1: systemctl 和 service 命令有什么区别?
service nginx start 是传统 SysV init 时代的命令,兼容性包装器。在 systemd 系统上,它最终还是会调用 systemctl。而 systemctl start nginx 是直接操作 systemd 的原生命令。建议统一使用 systemctl,输出更详细、功能更完整。
Q2: systemctl enable 和 systemctl start 必须一起用吗?
enable 只设置开机自启(创建符号链接),start 是立即启动。你可以只 start 不 enable(本次开机运行,重启后不自动启动),也可以只 enable 不 start(下次重启后自动启动)。但实战中常用 systemctl enable --now 一步到位解决两个需求。
Q3: 修改了 .service 文件后为什么 systemctl restart 没有用?
systemctl daemon-reload 让 systemd 重新加载配置,然后再 systemctl restart 服务名。这是新手最常见的错误,没有之一。