Systemd 是现代 Linux 系统的核心组件,负责系统初始化和服务管理。本文将全面介绍 Systemd 和 Systemctl 的使用方法,从基础操作到高级配置。

Systemd 简介

什么是 Systemd

Systemd 是 Linux 系统的初始化系统和服务管理器,它替代了传统的 SysV init 系统。主要特点包括:

  • 并行启动:提高系统启动速度
  • 按需启动:只在需要时启动服务
  • 依赖管理:自动处理服务间的依赖关系
  • 统一管理:提供统一的服务管理接口
  • 日志集成:集成了完整的日志系统

核心概念

  • Unit(单元):Systemd 管理的基本对象,包括服务、挂载点、设备等
  • Service(服务):最常见的 Unit 类型,用于管理后台进程
  • Target(目标):类似于传统的运行级别,定义系统状态
  • Socket(套接字):用于进程间通信的 Unit

Unit 类型

类型扩展名描述
Service.service系统服务
Target.target多个 Unit 的组合
Socket.socket套接字
Mount.mount挂载点
Timer.timer定时器
Path.path路径监控

Systemctl 基础命令

服务控制命令

启动和停止服务

# 启动服务
systemctl start <service_name>
systemctl start nginx

# 停止服务
systemctl stop <service_name>
systemctl stop nginx

# 重启服务
systemctl restart <service_name>
systemctl restart nginx

# 重新加载配置(不重启服务)
systemctl reload <service_name>
systemctl reload nginx

# 重新加载或重启(如果不支持 reload)
systemctl reload-or-restart <service_name>

服务状态查询

# 查看服务状态
systemctl status <service_name>
systemctl status nginx

# 检查服务是否运行
systemctl is-active <service_name>

# 检查服务是否启用
systemctl is-enabled <service_name>

# 检查服务是否失败
systemctl is-failed <service_name>

开机启动管理

# 设置开机启动
systemctl enable <service_name>
systemctl enable nginx

# 取消开机启动
systemctl disable <service_name>
systemctl disable nginx

# 启用并立即启动
systemctl enable --now <service_name>

# 禁用并立即停止
systemctl disable --now <service_name>

# 屏蔽服务(完全禁用)
systemctl mask <service_name>

# 取消屏蔽
systemctl unmask <service_name>

系统管理命令

系统状态和信息

# 查看系统状态
systemctl status

# 列出所有服务
systemctl list-units --type=service

# 列出所有启用的服务
systemctl list-unit-files --type=service --state=enabled

# 列出失败的服务
systemctl --failed

# 查看启动时间
systemd-analyze

# 查看启动时间详情
systemd-analyze blame

# 查看启动链
systemd-analyze critical-chain

系统控制

# 重启系统
systemctl reboot

# 关闭系统
systemctl poweroff

# 挂起系统
systemctl suspend

# 休眠系统
systemctl hibernate

# 进入救援模式
systemctl rescue

# 进入紧急模式
systemctl emergency

配置管理

# 重新加载 systemd 配置
systemctl daemon-reload

# 重新执行所有生成器
systemctl daemon-reexec

# 清理失效的符号链接
systemctl reset-failed

服务状态详解

服务状态类型

状态描述
active (running)服务正在运行
active (exited)服务已成功执行并退出
active (waiting)服务正在等待事件
inactive (dead)服务未运行
activating服务正在启动
deactivating服务正在停止
failed服务启动失败

启用状态类型

状态描述
enabled开机启动已启用
disabled开机启动已禁用
static服务不能被启用,只能被其他服务依赖
masked服务被屏蔽,无法启动
indirect服务被其他启用的服务间接启用

自定义服务配置

服务文件位置

# 系统服务目录(优先级高)
/etc/systemd/system/

# 软件包安装的服务目录
/lib/systemd/system/
/usr/lib/systemd/system/

# 用户服务目录
~/.config/systemd/user/

创建自定义服务

1. 创建服务文件

# 创建服务文件
sudo vim /etc/systemd/system/myapp.service

2. 基本服务配置

[Unit]
Description=My Application Service
Documentation=https://example.com/docs
After=network.target
Wants=network-online.target
Requires=network.target

[Service]
Type=simple
User=myuser
Group=mygroup
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/myapp --config /opt/myapp/config.conf
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -TERM $MAINPID
Restart=on-failure
RestartSec=5
TimeoutStartSec=30
TimeoutStopSec=30

# 安全设置
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/log/myapp

# 环境变量
Environment=NODE_ENV=production
EnvironmentFile=/etc/myapp/environment

[Install]
WantedBy=multi-user.target

配置文件详解

[Unit] 段配置

参数描述示例
Description服务描述Description=Redis Server
Documentation文档链接Documentation=man:redis-server(1)
After在指定服务后启动After=network.target
Before在指定服务前启动Before=nginx.service
Wants弱依赖关系Wants=network-online.target
Requires强依赖关系Requires=network.target
Conflicts冲突关系Conflicts=apache2.service

[Service] 段配置

参数描述可选值
Type服务类型simple, forking, oneshot, notify, idle
ExecStart启动命令完整的命令路径
ExecReload重载命令重载配置的命令
ExecStop停止命令停止服务的命令
Restart重启策略no, always, on-success, on-failure, on-abnormal
RestartSec重启间隔秒数,如 5
User运行用户用户名
Group运行组组名
WorkingDirectory工作目录目录路径

服务类型说明

  • simple:默认类型,ExecStart 启动的进程就是主进程
  • forking:ExecStart 启动的进程会 fork 出子进程,父进程退出
  • oneshot:类似 simple,但进程退出后服务仍被认为是活跃的
  • notify:类似 simple,但服务会通过 sd_notify() 发送就绪通知
  • idle:类似 simple,但会等到其他任务完成后才启动

[Install] 段配置

参数描述示例
WantedBy被哪个 target 需要multi-user.target
RequiredBy被哪个 target 强制需要graphical.target
Alias服务别名redis.service

实际配置示例

Redis 服务配置

[Unit]
Description=Redis In-Memory Data Store
After=network.target
Documentation=https://redis.io/documentation

[Service]
Type=notify
ExecStart=/usr/bin/redis-server /etc/redis/redis.conf
ExecReload=/bin/kill -USR2 $MAINPID
ExecStop=/usr/bin/redis-cli shutdown
TimeoutStartSec=0
Restart=always
User=redis
Group=redis

# 安全设置
NoNewPrivileges=yes
PrivateTmp=yes
PrivateDevices=yes
ProtectHome=yes
ProtectSystem=strict
ReadWritePaths=/var/lib/redis
ReadWritePaths=/var/log/redis

[Install]
WantedBy=multi-user.target

Node.js 应用服务配置

[Unit]
Description=Node.js Web Application
After=network.target

[Service]
Type=simple
User=nodejs
Group=nodejs
WorkingDirectory=/opt/webapp
ExecStart=/usr/bin/node app.js
Restart=on-failure
RestartSec=10
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=webapp

# 环境变量
Environment=NODE_ENV=production
Environment=PORT=3000

# 安全设置
NoNewPrivileges=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target

启用自定义服务

# 重新加载 systemd 配置
sudo systemctl daemon-reload

# 启用服务
sudo systemctl enable myapp.service

# 启动服务
sudo systemctl start myapp.service

# 查看服务状态
sudo systemctl status myapp.service

日志管理

Journalctl 基础使用

# 查看所有日志
journalctl

# 查看特定服务的日志
journalctl -u nginx.service

# 实时查看日志
journalctl -u nginx.service -f

# 查看最近的日志
journalctl -u nginx.service -n 50

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

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

# 查看昨天的日志
journalctl -u nginx.service --since yesterday

# 查看最近一小时的日志
journalctl -u nginx.service --since "1 hour ago"

日志过滤和格式

# 按优先级过滤日志
journalctl -u nginx.service -p err

# 显示详细信息
journalctl -u nginx.service -o verbose

# JSON 格式输出
journalctl -u nginx.service -o json

# 只显示消息内容
journalctl -u nginx.service -o cat

# 反向显示(最新的在前)
journalctl -u nginx.service -r

日志清理和维护

# 查看日志占用空间
journalctl --disk-usage

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

# 清理日志(保留最近100MB)
sudo journalctl --vacuum-size=100M

# 清理日志(保留最近10个文件)
sudo journalctl --vacuum-files=10

故障排查

常见问题诊断

1. 服务启动失败

# 查看服务状态
systemctl status service_name

# 查看详细错误信息
journalctl -u service_name -n 50

# 检查配置文件语法
systemd-analyze verify /etc/systemd/system/service_name.service

2. 服务依赖问题

# 查看服务依赖关系
systemctl list-dependencies service_name

# 查看反向依赖
systemctl list-dependencies service_name --reverse

# 分析启动链
systemd-analyze critical-chain service_name

3. 权限问题

# 检查文件权限
ls -la /etc/systemd/system/service_name.service

# 检查用户和组
id username

# 检查 SELinux 状态(如果启用)
getenforce

调试技巧

1. 启用调试模式

# 临时启用调试
sudo systemctl set-log-level debug

# 恢复正常日志级别
sudo systemctl set-log-level info

2. 手动测试服务

# 手动运行服务命令
sudo -u service_user /path/to/service/command

# 检查配置文件
sudo -u service_user /path/to/service/command --test-config

3. 使用 strace 跟踪

# 跟踪服务启动过程
sudo strace -f -o /tmp/service.trace systemctl start service_name

高级功能

定时器(Timer)

创建定时器服务

# /etc/systemd/system/backup.service
[Unit]
Description=Backup Service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily
Requires=backup.service

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

管理定时器

# 启用定时器
sudo systemctl enable backup.timer
sudo systemctl start backup.timer

# 查看定时器状态
systemctl list-timers

# 查看特定定时器
systemctl status backup.timer

套接字激活

创建套接字服务

# /etc/systemd/system/myapp.socket
[Unit]
Description=MyApp Socket

[Socket]
ListenStream=8080
Accept=no

[Install]
WantedBy=sockets.target
# /etc/systemd/system/myapp.service
[Unit]
Description=MyApp Service
Requires=myapp.socket

[Service]
Type=simple
ExecStart=/usr/local/bin/myapp
StandardInput=socket

资源限制

[Service]
# CPU 限制
CPUQuota=50%

# 内存限制
MemoryLimit=512M

# 文件描述符限制
LimitNOFILE=65536

# 进程数限制
LimitNPROC=4096

# 任务数限制
TasksMax=100

最佳实践

1. 服务配置建议

  • 使用非 root 用户运行服务
  • 设置适当的工作目录
  • 配置合理的重启策略
  • 启用安全特性(PrivateTmp、ProtectSystem 等)
  • 设置资源限制

2. 日志管理建议

  • 定期清理日志文件
  • 设置合适的日志级别
  • 使用结构化日志格式
  • 配置日志轮转

3. 监控和维护

  • 定期检查服务状态
  • 监控系统资源使用
  • 及时处理失败的服务
  • 保持系统和服务更新

4. 安全考虑

  • 最小权限原则
  • 使用专用用户账户
  • 启用 systemd 安全特性
  • 定期审查服务配置

常用命令速查

服务管理

systemctl start/stop/restart/reload service_name
systemctl enable/disable service_name
systemctl status service_name
systemctl is-active/is-enabled service_name

系统管理

systemctl list-units --type=service
systemctl --failed
systemctl daemon-reload
systemd-analyze

日志查看

journalctl -u service_name
journalctl -u service_name -f
journalctl -u service_name --since today

总结

Systemd 和 Systemctl 是现代 Linux 系统管理的核心工具。掌握它们的使用方法对于系统管理员和开发人员都非常重要。主要要点:

  1. 理解基本概念:Unit、Service、Target 等
  2. 熟练使用命令:服务控制、状态查询、日志管理
  3. 掌握配置编写:服务文件的结构和参数
  4. 学会故障排查:使用日志和调试工具
  5. 遵循最佳实践:安全、性能、维护等方面

通过系统学习和实践,可以更好地管理 Linux 系统服务,提高系统的稳定性和安全性。

参考资料

  1. Systemd 官方文档
  2. Systemd 入门教程:命令篇
  3. Systemd 入门教程:实战篇
  4. ArchLinux Systemd Wiki
  5. Red Hat Systemd 指南