Systemd 入门实战:手写 unit 文件,优雅管理你的服务

举报
yd_282444815 发表于 2026/10/31 09:18:17 2026/10/31
【摘要】 现在稍微新一点的 Linux 发行版,开机后的第一个进程(PID 1)几乎都是 systemd。从 CentOS 7、Ubuntu 16.04、Debian 8 开始,它全面接管了传统 SysV init 的工作。你每天随手敲的 systemctl start nginx、systemctl enable docker,背后都是它在干活。理解 systemd,是从“会用 Linux”走向“能...

现在稍微新一点的 Linux 发行版,开机后的第一个进程(PID 1)几乎都是 systemd。从 CentOS 7、Ubuntu 16.04、Debian 8 开始,它全面接管了传统 SysV init 的工作。你每天随手敲的 systemctl start nginx、systemctl enable docker,背后都是它在干活。理解 systemd,是从“会用 Linux”走向“能运维 Linux”的关键一步。

一、systemd 到底是什么

传统 SysV init 是串行启动服务的:一堆脚本按编号顺序执行,前一个慢了,后面全都得等着。systemd 换了一套思路:

  • 并行启动:根据依赖关系图,同时启动互不依赖的服务,开机更快;
  • 按需激活:socket、path、timer 等多种触发方式,服务不用常驻也能响应请求;
  • cgroup 统一管理:每个服务都在自己的 cgroup 里,资源隔离、进程追踪更干净,再也不会出现“服务停了但子进程还在跑”的尴尬;
  • 声明式配置:服务怎么启、挂了怎么办、依赖谁,全写在一个 unit 文件里,一目了然。

二、核心概念:unit

systemd 管理的一切都叫 unit,类型有十几种,日常打交道最多的就这几个:

类型 后缀 用途
service .service 系统服务,最常用
target .target 一组 unit 的集合,类似“运行级别”
timer .timer 定时任务,可替代 cron
socket .socket 套接字激活,按需拉起服务
path .path 路径变化时触发服务

unit 文件放在两个地方:系统自带的在 /lib/systemd/system/,管理员自定义的在 /etc/systemd/system/,后者优先级更高。想覆盖系统默认行为,把文件拷到 /etc/systemd/system/ 下改就行,系统升级也不会丢。

三、systemctl:每天都在用的命令

systemctl start nginx        # 启动服务
systemctl stop nginx         # 停止服务
systemctl restart nginx      # 重启服务
systemctl reload nginx       # 重载配置(不断服务)
 systemctl enable nginx       # 开机自启
systemctl disable nginx      # 取消开机自启
systemctl status nginx       # 查看状态,最常用
systemctl is-active nginx    # 只看是否在运行
systemctl list-units --type=service --state=running  # 列出运行中的服务

排查问题三板斧:systemctl status 看状态和最近日志,journalctl -u nginx -f 实时跟日志,systemd-analyze blame 看开机时哪个服务最慢。

四、实战:手写一个 service 文件

假设你写了一个 Python 小服务 app.py,监听 8080 端口。以前的做法可能是 nohup python app.py &,机器一重启就没了,还得自己写守护脚本。现在用 systemd,几分钟搞定。

1. 创建 unit 文件 /etc/systemd/system/myapp.service:

[Unit]
Description=My Python App
After=network.target
Wants=network.target

[Service]
Type=simple
User=appuser
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/python3 /opt/myapp/app.py
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

几个关键字段解释一下:

  • After=network.target:网络就绪后再启动,避免服务起来时网络还没好;
  • Type=simple:默认类型,ExecStart 启动的进程就是主进程;
  • Restart=on-failure:异常退出自动重启,配合 RestartSec=5 等 5 秒再拉起,避免疯狂重启打爆日志;
  • WantedBy=multi-user.target:决定 enable 时挂到哪个 target 下面。

2. 重载配置并启动:

sudo systemctl daemon-reload      # 每次改完 unit 文件都要执行
sudo systemctl enable --now myapp  # 开机自启 + 立刻启动
systemctl status myapp

3. 看日志,不用再到处找 log 文件:

journalctl -u myapp -f                 # 实时跟踪
journalctl -u myapp --since "1 hour ago"  # 最近一小时的日志

systemd 把服务的标准输出直接收进 journal,日志从此有了统一入口。

五、几个容易踩的坑

  1. 改了 unit 文件没 daemon-reload:systemd 会缓存配置,不重载修改不生效,这是新手最高频的坑;
  2. Type 选错:程序自己会 fork 到后台的(比如默认配置的 nginx)要用 Type=forking,否则 systemd 以为进程退出了,会反复重启服务;
  3. 环境变量:unit 里没有你的 shell 环境,PATH、PYTHONPATH 这类要靠 Environment= 显式声明;
  4. 权限:用 User= 指定运行用户,别图省事全用 root 跑业务进程。

六、小结

systemd 的学习曲线其实很平缓:先会用 systemctl 管理服务,再学会写 service 文件解决“开机自启 + 挂掉重启”,最后按需探索 timer 替代 cron、socket 激活这些高级玩法。把这套东西吃透,你手里的每一台 Linux 服务器都会听话很多。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。