本文是一份面向 Debian / Ubuntu 的 systemd 实战指南,重点讲清楚如何理解 unit、使用 systemctl 管理服务、查看 journalctl 日志、编写自定义 service、使用 timer、做 override,以及排查常见启动失败问题。
适用场景
- 管理系统服务
- 启停 Web、数据库、SSH、Docker 等守护进程
- 为自定义程序编写开机自启服务
- 使用 timer 代替 cron 做定时任务
- 排查服务启动失败和资源限制问题
systemd 是什么
systemd 是 Linux 的系统和服务管理器。它在系统启动时作为 PID 1 运行,负责初始化和管理用户空间服务。
systemd 相关的核心工具有:
- systemctl:管理 unit
- journalctl:查看日志
- systemd-analyze:分析启动时间和依赖
- systemd-run:动态运行临时服务
核心概念
Unit
Unit 是 systemd 管理的对象,可以是:
- service
- socket
- timer
- target
- mount
- swap
- path
- slice
Service
*.service 是最常见的 unit,用来管理进程或守护程序。
Target
*.target 可以理解为一组 unit 的聚合点,类似更现代的运行级别概念。
Timer
*.timer 用来做定时任务,是 cron 的常见替代方案。
unit 文件位置
常见路径:
/etc/systemd/system/
/lib/systemd/system/
/usr/lib/systemd/system/一般规则:
- 自定义服务优先放 /etc/systemd/system/
- 系统包安装的服务通常在 /lib/systemd/system/ 或 /usr/lib/systemd/system/
systemctl 常用命令
查看状态
systemctl status nginx启停服务
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx
sudo systemctl reload nginx设置开机自启
sudo systemctl enable nginx
sudo systemctl disable nginx查看是否启用
systemctl is-enabled nginx
systemctl is-active nginx列出 unit
systemctl list-units
systemctl list-unit-files
systemctl list-dependencies nginx重新加载 systemd 配置
修改 unit 文件后,需要让 systemd 重新读取配置:
sudo systemctl daemon-reload这一步很重要。改了 .service 文件后不做 daemon-reload,系统可能还在用旧配置。
service 文件结构
一个常见的 service 文件由三部分组成:
- [Unit]
- [Service]
- [Install]
示例
[Unit]
Description=My App Service
After=network.target
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/myapp
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target常见字段说明
[Unit]
- Description:描述
- After:启动顺序依赖
- Requires:强依赖
- Wants:弱依赖
- Before:在谁之前启动
[Service]
- Type:服务类型
- User / Group:运行用户
- WorkingDirectory:工作目录
- ExecStart:启动命令
- ExecStop:停止命令
- Restart:重启策略
- RestartSec:重启间隔
- Environment:环境变量
- EnvironmentFile:环境变量文件
[Install]
- WantedBy:被哪个 target 拉起
常见 Type
- simple:最常见,启动命令即主进程
- exec:类似 simple,但更强调执行状态
- forking:旧式守护进程,启动后会 fork
- oneshot:一次性任务
- notify:通过 sd_notify 通知就绪
多数现代程序直接用 Type=simple 就够了。
编写自定义 service
假设你的程序在 /opt/myapp/myapp。
创建文件:
sudo nano /etc/systemd/system/myapp.service内容示例:
[Unit]
Description=MyApp Service
After=network.target
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/myapp
Restart=always
RestartSec=3
Environment=APP_ENV=prod
[Install]
WantedBy=multi-user.target应用配置:
sudo systemctl daemon-reload
sudo systemctl enable myapp
sudo systemctl start myapp日志查看
systemd 的日志主要通过 journalctl 查看。
查看服务日志
journalctl -u nginx跟随日志
journalctl -u nginx -f查看本次启动的日志
journalctl -u nginx -b查看错误级别日志
journalctl -p err -b清晰时间显示
journalctl -u nginx --since "today"override 与 drop-in
不要直接修改系统包提供的 unit 文件。更稳妥的方法是使用 override。
创建 override:
sudo systemctl edit nginx示例:
[Service]
Restart=always
RestartSec=2保存后,systemd 会把配置写到:
/etc/systemd/system/nginx.service.d/override.conf查看最终生效配置:
systemctl cat nginxenvironment 文件
有些服务会单独使用环境文件:
EnvironmentFile=/etc/default/myapp示例内容:
APP_ENV=prod
APP_PORT=8080timer
Timer 是 systemd 的定时任务机制,常用于替代 cron。
示例 service
[Unit]
Description=Backup Job
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh示例 timer
[Unit]
Description=Run backup every day at 03:00
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target启用:
sudo systemctl enable --now backup.timer查看 timer:
systemctl list-timerstarget
target 用于组织一组服务。
常见 target:
- multi-user.target
- graphical.target
- network.target
- timers.target
查看默认启动目标:
systemctl get-default常见排障
1. 服务启动失败
先看状态:
systemctl status myapp再看日志:
journalctl -u myapp -xe2. unit 改了没生效
执行:
sudo systemctl daemon-reload
sudo systemctl restart myapp3. 服务一直重启
检查:
- ExecStart 是否正确
- 程序是否马上退出
- Restart 策略是否合适
- 权限和工作目录是否正确
4. 端口没监听
检查程序是否真的起来:
ss -ltnp5. 环境变量没生效
检查:
- Environment 拼写
- EnvironmentFile 路径
- 是否重新加载和重启
性能与启动分析
查看启动耗时
systemd-analyze blame
systemd-analyze critical-chain查看 unit 依赖
systemctl list-dependencies nginx安全建议
- 自定义服务尽量不要直接用 root
- 不要随便改系统包 unit 文件本体
- 修改 service 后记得 daemon-reload
- 定时任务优先考虑 timer
- 日志排障优先看 journal
最小可用流程
如果你想快速把一个程序变成 systemd 服务:
sudo nano /etc/systemd/system/myapp.service
sudo systemctl daemon-reload
sudo systemctl enable myapp
sudo systemctl start myapp
systemctl status myapp
journalctl -u myapp -f结论
systemd 的核心是把“服务管理”标准化:
- 用 unit 表达服务和依赖
- 用 systemctl 管理状态
- 用 journalctl 看日志
- 用 override 做局部修改
- 用 timer 做定时任务
如果你要,我可以继续把这篇文档扩成更深入的版本,例如:
- systemd service 文件写法大全
- timer 替代 cron 的完整实战
- journalctl 高级过滤与排障
- systemd target / dependency 深入说明
- 自定义程序接入 systemd 的生产模板