跳转至

systemd 服务管理

systemd 是现代 Linux 的初始化系统和服务管理器,以 PID 1 运行,负责管理从开机到关机的所有进程、服务依赖、日志收集和系统状态切换。

核心知识点

概念说明
Unitsystemd 管理的基本单元,包括 service、timer、socket、mount 等
systemctl控制 systemd 的主命令行工具
journalctl查询 systemd 日志的工具
Unit File定义服务行为的配置文件,通常在 /etc/systemd/system/
Target一组 Unit 的集合,类似于传统的运行级别
Wants/Requires依赖关系:Wants 是弱依赖,Requires 是强依赖
After/Before控制启动顺序,不控制依赖关系

安装配置

# systemd 是现代 Linux 发行版自带的,不需要额外安装
# 查看 systemd 版本
systemctl --version  # 查看当前 systemd 版本号

# 查看系统是否使用 systemd 作为 init 系统
ps -p 1 -o comm=  # 如果输出 systemd,说明正在使用

基本使用

服务管理基础命令

# 启动服务(立即运行)
sudo systemctl start nginx  # 启动 nginx 服务

# 停止服务(立即停止)
sudo systemctl stop nginx  # 停止 nginx 服务

# 重启服务(先停后启)
sudo systemctl restart nginx  # 重启 nginx 服务

# 重新加载配置(不中断服务)
sudo systemctl reload nginx  # 让 nginx 重新读取配置文件

# 查看服务状态(最常用)
systemctl status nginx  # 查看 nginx 当前运行状态、PID、日志

# 设置开机自启
sudo systemctl enable nginx  # 开机时自动启动 nginx

# 取消开机自启
sudo systemctl disable nginx  # 取消 nginx 的开机自启

# 启动并同时设置开机自启(二合一)
sudo systemctl enable --now nginx  # 立即启动 + 设置开机自启

# 查看服务是否在运行
systemctl is-active nginx  # 返回 active 或 inactive

# 查看服务是否开机自启
systemctl is-enabled nginx  # 返回 enabled 或 disabled

查看系统服务

# 列出所有正在运行的服务
systemctl list-units --type=service  # 只显示 service 类型的 unit

# 列出所有已安装的服务(包括未启动的)
systemctl list-unit-files --type=service  # 显示所有服务文件及其状态

# 列出失败的服务
systemctl --failed  # 查看哪些服务启动失败了

# 查看服务的依赖关系
systemctl list-dependencies nginx  # 查看 nginx 依赖哪些服务

高级用法

编写自定义服务文件

# 创建一个自定义服务文件
sudo vim /etc/systemd/system/myapp.service  # 在系统服务目录下创建
# /etc/systemd/system/myapp.service
[Unit]
Description=My Application Server  # 服务描述
Documentation=https://myapp.example.com  # 文档链接
After=network.target  # 在网络服务启动后再启动
Requires=postgresql.service  # 强依赖 PostgreSQL,它挂了我也停
Wants=redis.service  # 弱依赖 Redis,它挂了我继续跑

[Service]
Type=simple  # 简单类型:启动后就算就绪(最常用)
User=myapp  # 以 myapp 用户运行(不用 root,安全)
Group=myapp  # 以 myapp 用户组运行
WorkingDirectory=/opt/myapp  # 工作目录
ExecStart=/opt/myapp/bin/server --config /etc/myapp/config.yaml  # 启动命令(必须用绝对路径)
ExecReload=/bin/kill -HUP $MAINPID  # reload 时发送 HUP 信号
Restart=on-failure  # 异常退出时自动重启(正常退出不重启)
RestartSec=5  # 重启前等待 5 秒
StartLimitBurst=3  # 连续重启次数限制
StartLimitIntervalSec=60  # 在 60 秒内最多重启 3 次

# 安全加固(2025+ 最佳实践)
PrivateTmp=true  # 私有 /tmp 目录,防止被其他进程读取
ProtectSystem=full  # 保护 /usr 和 /boot 为只读
ProtectHome=true  # 禁止访问 /home 目录
NoNewPrivileges=true  # 禁止提升权限
CapabilityBoundingSet=CAP_NET_BIND_SERVICE  # 只允许绑定低端口

# 资源限制
LimitNOFILE=65536  # 最大打开文件数
LimitNPROC=4096  # 最大进程数
MemoryMax=2G  # 最大内存使用 2GB
CPUQuota=200%  # 最多使用 2 个 CPU 核心

# 环境变量
Environment=NODE_ENV=production  # 设置环境变量
EnvironmentFile=/etc/myapp/env  # 从文件加载环境变量

[Install]
WantedBy=multi-user.target  # 在多用户模式下启用(类似运行级别 3)
# 修改服务文件后必须重新加载
sudo systemctl daemon-reload  # 让 systemd 重新读取所有 unit 文件

# 启动自定义服务
sudo systemctl enable --now myapp  # 启动并设置开机自启

服务模板(管理多个实例)

# /etc/systemd/system/myapp@.service(注意 @ 符号)
[Unit]
Description=My App Instance %i  # %i 会被替换为实例名

[Service]
User=myapp  # 运行用户
ExecStart=/opt/myapp/bin/server --port %i  # %i 替换为传入的参数
Restart=on-failure  # 失败时自动重启

[Install]
WantedBy=multi-user.target  # 多用户模式
# 启动多个实例,每个监听不同端口
sudo systemctl start myapp@8001  # 启动端口 8001 的实例
sudo systemctl start myapp@8002  # 启动端口 8002 的实例
sudo systemctl start myapp@8003  # 启动端口 8003 的实例

日志管理(journalctl)

# 查看某个服务的日志
journalctl -u nginx  # 查看 nginx 的所有日志

# 查看最近的日志(实时跟踪,类似 tail -f)
journalctl -u nginx -f  # 实时显示 nginx 新日志

# 查看最近 100 行日志
journalctl -u nginx -n 100  # 只显示最新 100 行

# 查看今天的日志
journalctl -u nginx --since today  # 只看今天的

# 查看指定时间段的日志
journalctl -u nginx --since "2025-01-01" --until "2025-01-02"  # 时间范围

# 按优先级过滤(err = 错误及以上)
journalctl -u nginx -p err  # 只看错误级别的日志

# 查看本次启动的日志
journalctl -u nginx -b  # 只看本次开机后的日志

# 查看日志占用磁盘空间
journalctl --disk-usage  # 看日志用了多少磁盘

# 清理旧日志(保留最近 7 天)
sudo journalctl --vacuum-time=7d  # 删除 7 天前的日志

定时器(替代 crontab)

# /etc/systemd/system/backup.timer
[Unit]
Description=Daily Backup Timer  # 每日备份定时器

[Timer]
OnCalendar=*-*-* 02:00:00  # 每天凌晨 2 点执行
Persistent=true  # 如果错过了执行时间(比如关机了),开机后补执行
RandomizedDelaySec=300  # 随机延迟 0-300 秒,避免同时执行

[Install]
WantedBy=timers.target  # 属于定时器目标
# 查看所有定时器
systemctl list-timers  # 列出所有活跃的定时器及下次执行时间

# 启用定时器
sudo systemctl enable --now backup.timer  # 启动定时器

常见报错

报错原因解决
Failed to start xxx: Unit not found服务文件不存在或名字写错检查 /etc/systemd/system/ 下的文件名
Main process exited, code=exited, status=203/EXECExecStart 路径错误或没有执行权限检查路径是否正确,用 chmod +x 加权限
code=exited, status=217/USERUser 指定的用户不存在useradd 创建用户
Start request repeated too quickly服务频繁崩溃重启超过限制检查应用日志,修复崩溃原因
Dependency failed for xxx依赖的服务启动失败先修复依赖服务的问题
修改服务文件后不生效没有执行 daemon-reload运行 sudo systemctl daemon-reload
Address already in use端口被其他程序占用ss -tlnp \| grep 端口号 查看占用

速查表

# === 服务生命周期 ===
systemctl start/stop/restart/reload 服务名   # 启动/停止/重启/重载
systemctl enable/disable 服务名               # 开机自启/取消自启
systemctl enable --now 服务名                 # 启动+开机自启二合一
systemctl status 服务名                       # 查看状态
systemctl is-active/is-enabled 服务名         # 检查运行/自启状态

# === 查看与排查 ===
systemctl list-units --type=service           # 列出运行中的服务
systemctl list-unit-files --type=service      # 列出所有服务文件
systemctl --failed                            # 查看失败的服务
systemctl list-dependencies 服务名            # 查看依赖关系
systemctl cat 服务名                          # 查看服务文件内容

# === 日志 ===
journalctl -u 服务名                          # 查看服务日志
journalctl -u 服务名 -f                       # 实时跟踪日志
journalctl -u 服务名 -n 100                   # 最新 100 行
journalctl -u 服务名 --since today            # 今天的日志
journalctl -u 服务名 -p err                   # 只看错误

# === 系统管理 ===
systemctl daemon-reload                        # 重新加载所有 unit 文件
systemctl list-timers                          # 查看定时器
systemctl isolate multi-user.target            # 切换到多用户模式
systemctl isolate graphical.target             # 切换到图形界面
systemctl get-default                          # 查看默认启动目标