Linux 服务管理基础:Systemd 入门与运维实践
一、Systemd 的诞生背景与核心优势
Systemd 由 Lennart Poettering 于 2010 年左右发起,旨在解决传统 init 系统的痛点:
- 启动速度慢:SysVinit 是串行启动,Systemd 支持并行启动。
- 依赖管理弱:传统脚本依赖关系通过数字前缀(S01、K01)实现,脆弱且难以维护。
- 管理分散:日志、电源管理、设备管理等分散在不同工具中。
- 缺乏统一接口:没有标准化的服务状态查询和控制方式。
Systemd 的设计哲学是“一切皆单元”(Everything is a unit),通过单元(Unit)来统一管理服务(Service)、挂载点(Mount)、设备(Device)、定时任务(Timer)、套接字(Socket)、路径(Path)、Slice(资源控制)等。
核心优势(运维视角):
- 极致启动速度:依赖树分析 + 并行启动 + 按需启动(socket activation)。
- 强大依赖管理:After=、Before=、Wants=、Requires=、BindsTo= 等精确控制。
- 统一日志系统:journald 提供结构化日志、实时查看、持久化。
- 资源控制集成:原生支持 cgroups v1/v2,实现 CPU、内存、IO 限制。
- 安全性提升:PrivateTmp、ProtectSystem、CapabilityBoundingSet 等沙箱机制。
- DBus 集成:现代工具(如 systemctl、journalctl)通过 D-Bus 通信,自动化友好。
在生产环境中,如果你还在使用 service 命令或 /etc/init.d/ 脚本,强烈建议立即迁移到 Systemd。
二、Systemd 架构详解
Systemd 由多个组件组成:
- systemd:PID 1 主进程,负责启动系统、挂载文件系统、管理服务。
- systemd-networkd:网络配置(可选)。
- systemd-resolved:DNS 解析(可选)。
单元类型(常见 12 种):
- .target:类似运行级别(multi-user.target、graphical.target)。
- .timer:定时器(替代 crontab 的更好选择)。
单元文件搜索路径优先级(从高到低):
- /etc/systemd/system/ (管理员自定义,最高优先级)
- /usr/lib/systemd/system/ (系统默认)
三、systemctl 核心命令详解(运维必备)
1. 服务基础操作
systemctl start nginx.service # 启动
systemctl stop nginx.service # 停止
systemctl restart nginx.service # 重启
systemctl reload nginx.service # 重载配置(不中断)
systemctl status nginx.service # 详细状态
systemctl enable nginx.service # 开机自启
systemctl disable nginx.service # 取消自启
systemctl is-enabled nginx.service # 检查自启状态
2. 全局操作
systemctl daemon-reload # 重新加载所有单元(修改配置后必须执行)
systemctl reboot # 重启系统
systemctl poweroff # 关机
systemctl suspend# 挂起
systemctl list-units --type=service # 列出所有服务
systemctl list-unit-files # 列出所有单元文件
3. 日志相关
journalctl -u nginx.service # 查看某服务日志
journalctl -u nginx.service -f # 实时追踪
journalctl -u nginx -xe # 最近错误
journalctl --since "2025-05-01" --until "2025-05-02"
journalctl -p err # 只看错误及以上级别
4. 资源与状态
systemctl show nginx.service # 显示所有属性
systemd-cgtop # cgroups 资源监控
systemctl list-dependencies multi-user.target # 查看依赖树
生产运维技巧:
- 使用
systemctl status -l 查看完整日志输出。 systemctl kill -s SIGTERM nginx.service 优雅终止。systemctl mask nginx.service 彻底禁用(防止意外启动)。
四、单元文件(.service)完整编写指南
一个完整的生产级服务单元文件示例(以 nginx 为例):
[Unit]
Description=The NGINX HTTP and reverse proxy server
Documentation=https://nginx.org/en/docs/
After=network.target remote-fs.target nss-lookup.target
Wants=network-online.target
[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=/bin/kill -s QUIT $MAINPID
TimeoutStopSec=5
KillMode=mixed
LimitNOFILE=65535
LimitCORE=infinity
# 安全强化
PrivateTmp=true
ProtectSystem=strict
ProtectHome=read-only
NoNewPrivileges=true
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SYS_ADMIN
ReadWritePaths=/var/log/nginx /var/cache/nginx
[Install]
WantedBy=multi-user.target
关键字段详解:
Wants=、Requires=、BindsTo=:依赖关系差异(Wants 失败不影响本单元,Requires 失败则停止本单元)。
Type=:simple(默认)、forking(传统 daemon)、oneshot、dbus、notify、idle。ExecStart、ExecStartPre、ExecStop、ExecReload。Restart=:always、on-failure、on-abnormal 等。Environment=、EnvironmentFile=:环境变量。- 资源限制:
LimitNOFILE、LimitNPROC、MemoryMax=(cgroups)。
[Install] 段:WantedBy= 指定 target。
生产建议:
- 重要服务使用
Restart=always + RestartSec=3。 - 数据库类服务(如 mysql、postgresql)建议
Type=notify 并配合 Type=notify 的 watchdog。 - 大内存服务设置
OOMPolicy=continue 防止被 OOM Killer 杀死。
五、生产环境最佳实践
- 自定义服务放
/etc/systemd/system/。 - 覆盖系统服务:复制
/usr/lib/systemd/system/xxx.service 到 /etc/systemd/system/ 后修改。
- 最小权限原则:使用
User=nobody 或专用用户。 - 启用 SELinux(enforcing 模式)并正确设置上下文。
- 使用
systemd-analyze security nginx.service 检查安全评分。
- Keepalived + VIP + Systemd 服务。
- 多实例服务使用不同端口 + 不同 service 文件(如 nginx@.service 模板)。
- Prometheus + node_exporter + systemd_exporter。
- 关键指标:ActiveState、SubState、MemoryCurrent、CPUUsageNSec。
- 定期备份
/etc/systemd/system/ 和重要服务配置文件。
六、常见故障排查案例(运维实战)
案例1:服务启动失败(权限问题) 症状:systemctl status 显示 "Permission denied"。 排查:
journalctl -u xxx -xe
ls -lZ /var/run/xxx.pid
ausearch -m avc -ts recent # SELinux
案例2:依赖循环systemd-analyze verify xxx.service 或 systemctl list-dependencies --reverse
案例3:启动极慢systemd-analyze blame 查看耗时单元 systemd-analyze plot > boot.svg 生成启动图
案例4:journal 日志爆盘
journalctl --vacuum-time=2weeks
journalctl --vacuum-size=500M
# /etc/systemd/journald.conf 中设置 SystemMaxUse=2G
案例5:cgroups 资源限制生效问题 确认使用 cgroups v2(stat -fc %T /sys/fs/cgroup/),合理设置 MemoryHigh/MemoryMax。