systemd 服务管理

在你部署的任何稍正式的 Linux 服务器上,后台跑的程序(Nginx、MySQL、Docker、你自己的应用)几乎都是 systemd 管理的。它是现代 Linux(PID 1)的标准服务管理器,负责启动、停止、监控、开机自启、收集日志。掌握 systemd 是从"会用 Linux"到"会部署"的关键一步

1. 什么是 systemd

systemd 是 2010 年后逐渐取代传统 SysV init 的初始化系统。开机时它是第一个跑的进程(PID 1),负责启动所有其他系统服务。它管理的对象叫 unit(单元),最常见的是 service(服务),还有 timer(定时器)、socket、mount 等。

对开发者来说,systemd 解决一个核心问题:怎么让自己的程序像 Nginx 一样在后台稳定运行、开机自启、崩溃自动重启、日志统一收集。答案是写一个 service unit 文件,用 systemctl 管理。

2. systemctl:基本操作

systemctl 是操作 systemd 的命令。最常用的就是 start/stop/restart/status 四件套:

# systemd:现代 Linux 的服务管理器(PID 1)

# 服务(service / daemon):长期运行的后台程序
#   nginx、mysql、sshd、docker 都是服务

# systemctl 是操作服务的命令
sudo systemctl start nginx         # 启动
sudo systemctl stop nginx          # 停止
sudo systemctl restart nginx       # 重启(改完配置后常用)
sudo systemctl reload nginx        # 重新加载配置(不断连接,比 restart 温和)
sudo systemctl status nginx        # 查看状态(最常用)

# status 输出示例:
#   nginx.service - The nginx HTTP and reverse proxy server
#      Loaded: loaded (/lib/systemd/system/nginx.service; enabled)
#      Active: active (running) since ...     <- 运行中
#   Main PID: 1234 (nginx)
#      Tasks: 2
#     Memory: 5.2M
#        CPU: 100ms

status 是最高频的——看服务在不在运行、有没有报错。关键看 Active: active (running)(正常)还是 failed(出错)。reloadrestart 温和:不停服务就重新读配置,适合 Nginx 改配置后不希望断开连接的场景。

3. enable:开机自启

区别两个概念:start 是"现在启动一次",关机后就没了;enable 是"注册开机自启",下次开机自动启动。两者是独立的——可以 enable 但不 start(下次开机才起),也可以 start 但不 enable(只这次启动)。

# 开机自启管理

# enable:注册开机自启(创建符号链接到启动目录)
sudo systemctl enable nginx        # 下次开机自动启动
sudo systemctl disable nginx       # 取消开机自启

# enable 不会立刻 start,要分开做
sudo systemctl enable --now nginx  # --now:同时启动(enable + start)

# 查看开机自启的服务
systemctl list-unit-files --type=service --state=enabled
#   nginx.service    enabled
#   docker.service   enabled
#   ssh.service      enabled

# 查看所有服务(含未启用的)
systemctl list-units --type=service
systemctl list-units --type=service --state=running    # 正在运行的
systemctl list-units --type=service --state=failed     # 失败的

装完数据库、Web 服务器后,标准做法是 sudo systemctl enable --now 服务名——同时启动并设置开机自启。--now 是 enable/start 二合一,很方便。

4. journalctl:统一日志

传统 Linux 各服务的日志散落在 /var/log 各处,systemd 把它们统一收集到 journal 里,用 journalctl 一个命令查所有。这是排查问题最强工具。

# journalctl:查看 systemd 收集的日志(统一日志系统)

# 看某个服务的日志
sudo journalctl -u nginx                  # nginx 所有日志
sudo journalctl -u nginx -f               # -f 实时跟随(等于 tail -f)
sudo journalctl -u nginx --since today    # 今天的
sudo journalctl -u nginx --since "1 hour ago"  # 最近 1 小时
sudo journalctl -u nginx -n 100           # 最后 100 条

# 看所有日志
sudo journalctl                           # 全部(很多)
sudo journalctl --since "2024-08-05"      # 某天起
sudo journalctl -p err                    # 只看错误级别(priority)
#   级别:emerg alert crit err warning notice info debug

# 看内核日志(类似 dmesg)
sudo journalctl -k

# 看本次启动的日志
sudo journalctl -b
sudo journalctl -b -1                     # 上一次启动的(系统崩溃后排查)

# 输出不分页(管道用)
sudo journalctl -u nginx --no-pager | tail -n 50

高频组合:journalctl -u 服务名 -f 实时跟随日志(等于 tail -f 但不用知道日志文件在哪)。系统出问题先 journalctl -p err 看所有错误。

5. 写一个自己的 service

这是 systemd 最实用的部分。把你的应用(一个 Node.js 服务、Python 脚本、Go 二进制)做成 systemd service,就拥有了和 Nginx 一样的待遇——后台运行、开机自启、崩溃重启、统一日志。

# 编写自己的 service:unit 文件

# 示例:把一个 Node.js 应用做成服务
# 创建文件:/etc/systemd/system/myapp.service

[Unit]
Description=My Node.js App              # 描述
After=network.target                    # 在网络服务之后启动(依赖)

[Service]
Type=simple                             # 简单类型(forking/oneshot 等)
User=deploy                             # 以 deploy 用户身份运行
WorkingDirectory=/opt/myapp             # 工作目录
ExecStart=/usr/bin/node server.js       # 启动命令(必须绝对路径)
Restart=on-failure                      # 崩溃后自动重启
RestartSec=5                            # 重启间隔 5 秒
Environment=NODE_ENV=production         # 环境变量
Environment=PORT=3000

[Install]
WantedBy=multi-user.target              # 在多用户模式下启用(开机自启)

几个关键字段:

6. 管理自定义服务的完整流程

# 管理自定义服务

# 1. 写完 unit 文件后,让 systemd 重新加载
sudo systemctl daemon-reload            # 通知 systemd 配置变了

# 2. 启动并设置开机自启
sudo systemctl enable --now myapp

# 3. 查看状态
sudo systemctl status myapp
#   Active: active (running) 即正常

# 4. 看日志
sudo journalctl -u myapp -f

# 5. 修改 unit 文件后(改完配置)
sudo systemctl daemon-reload            # 先 reload 配置
sudo systemctl restart myapp            # 再重启服务

# 6. 卸载服务
sudo systemctl disable --now myapp      # 停止并取消自启
sudo rm /etc/systemd/system/myapp.service
sudo systemctl daemon-reload

最常被忘的一步是 systemctl daemon-reload。每次修改 unit 文件后必须执行,否则 systemd 还在用旧配置。这是新手最常见的"我改了为啥没生效"的原因。

7. 实战:部署一个 Node.js 应用

把前面的知识串起来,完整流程:

这套流程对所有语言通用——Python 换 ExecStart 为 /usr/bin/python3 app.py,Go 换成编译好的二进制路径即可。

8. systemd timer:替代 cron(进阶)

传统定时任务用 cron,systemd 提供了更强的 timer 单元,有依赖管理、错误日志、错过补跑等优势:

# systemd timer:替代 cron 的定时任务(进阶)

# 写一个 timer unit,定时触发对应 service
# /etc/systemd/system/backup.service
[Unit]
Description=Backup Service
[Service]
ExecStart=/opt/scripts/backup.sh

# /etc/systemd/system/backup.timer
[Unit]
Description=Daily Backup
[Timer]
OnCalendar=daily                        # 每天(也支持 *-*-* 03:00:00)
Persistent=true                         # 错过了开机后补跑

[Install]
WantedBy=timers.target

# 启用 timer(不是 service)
sudo systemctl enable --now backup.timer
systemctl list-timers                   # 看所有定时任务

timer 在现代发行版里越来越流行,但 cron 简单够用,日常两者都行。

9. 常见问题

小结

这一篇你学会了 systemd 服务管理:systemctl 启停重启查状态、enable --now 开机自启、journalctl 查日志、写 service unit 文件把自己的程序做成服务。这是 Linux 工程化的核心——掌握它,你就能像专业运维一样部署和管理任何服务。恭喜你完成了 Linux 入门系列!

下一步学什么?

Linux 命令行的特点是"入门陡、精通后无敌"。坚持用一周,你会发现它比图形界面快十倍,而且一旦学会,在任何发行版、任何服务器、任何容器里都能用——这是一辈子的技能。

← 上一篇 SSH 远程连接

← 返回 Linux 教程目录

✈️💬