# 系统服务管理（systemd）

URL: https://caijiao.org/rockylinux/service-management
Source: docs/rockylinux/service-management.md
Description: 详细介绍 Rocky Linux 中使用 systemd 进行系统服务管理的方法，包括服务的启动、停止、重启、状态查询和配置等内容

systemd 是现代 Linux 发行版（包括 Rocky Linux）中默认的初始化系统和服务管理器。它负责在系统启动时启动系统服务，管理运行中的服务，并在系统关闭时正确终止它们。本教程将详细介绍如何在 Rocky Linux 中使用 systemd 管理系统服务，包括服务的启动、停止、重启、状态查询和配置等内容。

## systemd 概述

### systemd 基础概念

systemd 是一个系统和服务管理器，设计用于替代传统的 SysV init 和 Upstart 初始化系统。它的主要目标是提供更快速的启动速度、更好的并行化任务处理能力和更强大的服务管理功能。

systemd 的核心概念包括：

- **单元（Units）**：systemd 管理的基本对象，可以是服务、套接字、挂载点等
- **服务（Services）**：长时间运行的进程，如网络服务、数据库等
- **目标（Targets）**：类似于传统运行级别的概念，定义了系统的特定运行状态
- **依赖关系**：控制服务的启动顺序和依赖条件
- **计时器（Timers）**：替代传统的 cron 任务的定时执行机制

### systemd 单元类型

systemd 支持多种类型的单元，每种类型用于管理不同的系统资源：

| 单元类型 | 文件名后缀 | 描述 |
|---------|-----------|------|
| service | .service | 系统服务 |
| socket | .socket | 网络套接字或 IPC 套接字 |
| device | .device | 设备文件 |
| mount | .mount | 文件系统挂载点 |
| automount | .automount | 自动挂载点 |
| swap | .swap | 交换分区 |
| target | .target | 目标（类似运行级别） |
| path | .path | 文件系统路径 |
| timer | .timer | 定时器（替代 cron） |
| slice | .slice | 资源控制单元 |
| scope | .scope | 外部创建的进程组 |

## 基本服务管理命令

### 查看服务状态

```bash
# 查看单个服务的状态
systemctl status service-name.service

# 示例
systemctl status sshd.service
systemctl status nginx.service

# 可以省略 .service 后缀
systemctl status sshd

# 查看所有服务状态
systemctl list-units --type=service

# 查看所有已启动的服务
systemctl list-units --type=service --state=running

# 查看所有已安装但未运行的服务
systemctl list-units --type=service --state=inactive
```

### 控制服务

```bash
# 启动服务
systemctl start service-name

# 停止服务
systemctl stop service-name

# 重启服务
systemctl restart service-name

# 重新加载服务配置（不中断服务）
systemctl reload service-name

# 强制重新加载配置并重启服务
systemctl reload-or-restart service-name

# 条件性重启服务（仅当服务正在运行时）
systemctl try-restart service-name

# 暂停服务（挂起）
systemctl suspend service-name

# 恢复暂停的服务
systemctl resume service-name
```

### 启用和禁用服务

```bash
# 启用服务（系统启动时自动启动）
systemctl enable service-name

# 禁用服务（系统启动时不自动启动）
systemctl disable service-name

# 查看服务是否启用
systemctl is-enabled service-name

# 启用服务但不立即启动
systemctl enable --now service-name

# 禁用服务并立即停止
systemctl disable --now service-name
```

### 服务依赖关系

```bash
# 查看服务依赖
systemctl list-dependencies service-name

# 查看哪些服务依赖于指定服务
systemctl list-dependencies --reverse service-name

# 示例：查看 SSH 服务依赖
systemctl list-dependencies sshd
```

## 系统运行级别（Targets）

### 运行级别与 Target

systemd 使用 Targets 概念替代了传统的运行级别。以下是主要的 Targets 及其对应的传统运行级别：

| systemd Target | 传统运行级别 | 描述 |
|---------------|------------|------|
| poweroff.target | 0 | 关闭系统 |
| rescue.target | 1 | 单用户模式 |
| multi-user.target | 3 | 多用户文本模式 |
| graphical.target | 5 | 图形用户界面模式 |
| reboot.target | 6 | 重启系统 |

### 管理运行级别

```bash
# 查看当前运行的 Target
systemctl get-default

# 切换到 multi-user 运行级别
systemctl isolate multi-user.target

# 切换到图形界面运行级别
systemctl isolate graphical.target

# 设置默认运行级别（下次启动时生效）
systemctl set-default multi-user.target
systemctl set-default graphical.target

# 查看可用的 Targets
systemctl list-units --type=target
```

### 救援模式和紧急模式

```bash
# 进入救援模式
systemctl rescue

# 进入紧急模式
systemctl emergency
```

## 系统管理命令

### 系统状态和控制

```bash
# 查看系统运行状态
systemctl status

# 关闭系统
systemctl poweroff
systemctl halt
systemctl shutdown -h now

# 重启系统
systemctl reboot
systemctl shutdown -r now

# 暂停系统
systemctl suspend

# 休眠系统
systemctl hibernate

# 混合休眠（保存到磁盘并挂起）
systemctl hybrid-sleep
```

### 系统日志查看

```bash
# 查看系统日志
journalctl

# 查看特定服务的日志
journalctl -u service-name

# 实时查看日志
sudo journalctl -f

# 查看特定时间段的日志
journalctl --since "2023-05-01 10:00:00" --until "2023-05-01 12:00:00"

# 查看最近的日志
sudo journalctl -n 100

# 按优先级过滤日志
sudo journalctl -p err..emerg
```

## 服务配置文件

### 服务配置文件位置

systemd 服务配置文件主要存放在以下位置：

1. **/usr/lib/systemd/system/**：系统默认服务文件，由软件包管理器维护
2. **/etc/systemd/system/**：用户自定义或修改的服务文件，优先级高于 /usr/lib/systemd/system/
3. **/run/systemd/system/**：运行时生成的服务文件，重启后会丢失

### 服务文件结构

服务文件通常包含以下部分：

```ini
[Unit]
Description=描述信息
After=依赖的服务或目标
Requires=必须运行的服务
Wants=建议运行的服务

[Service]
Type=服务类型（simple, forking, oneshot, dbus, notify, idle）
ExecStart=启动命令
ExecStop=停止命令
ExecReload=重新加载配置命令
User=运行服务的用户
Group=运行服务的组
WorkingDirectory=工作目录
Restart=重启策略（no, on-success, on-failure, on-abnormal, on-watchdog, on-abort, always）
RestartSec=重启间隔时间

[Install]
WantedBy=目标（如 multi-user.target）
```

### 常用服务类型

- **simple**：默认类型，systemd 启动服务后继续执行后续操作
- **forking**：服务启动后会创建子进程，父进程退出
- **oneshot**：服务只执行一次，完成后退出
- **dbus**：服务依赖 D-Bus 通信
- **notify**：服务启动完成后会发送通知
- **idle**：systemd 等待所有其他任务完成后才启动服务

## 创建和修改服务文件

### 创建自定义服务

下面是创建自定义服务的步骤：

1. **创建服务文件**：
   ```bash
   sudo vim /etc/systemd/system/my-service.service
   ```

2. **编写服务内容**：
   ```ini
   [Unit]
   Description=My Custom Service
   After=network.target
   
   [Service]
   Type=simple
   User=username
   ExecStart=/path/to/executable
   Restart=on-failure
   RestartSec=5s
   
   [Install]
   WantedBy=multi-user.target
   ```

3. **重新加载 systemd 配置**：
   ```bash
   sudo systemctl daemon-reload
   ```

4. **启动和启用服务**：
   ```bash
   sudo systemctl start my-service
   sudo systemctl enable my-service
   ```

### 修改现有服务

修改现有服务有两种方法：

1. **直接修改服务文件**（不推荐）：
   ```bash
   sudo vim /usr/lib/systemd/system/service-name.service
   sudo systemctl daemon-reload
   sudo systemctl restart service-name
   ```

2. **创建服务覆盖目录**（推荐）：
   ```bash
   sudo mkdir -p /etc/systemd/system/service-name.service.d/
   sudo vim /etc/systemd/system/service-name.service.d/override.conf
   ```

   在 override.conf 中只包含要修改的部分，例如：
   ```ini
   [Service]
   Restart=on-failure
   RestartSec=10s
   ```

   然后重新加载并重启：
   ```bash
   sudo systemctl daemon-reload
   sudo systemctl restart service-name
   ```

### 示例：创建 Python 应用服务

```ini
[Unit]
Description=Python Web Application
After=network.target

[Service]
User=appuser
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/python3 app.py
Restart=on-failure
RestartSec=10
Environment=PYTHONPATH=/opt/myapp
Environment=APP_ENV=production

[Install]
WantedBy=multi-user.target
```

## 使用 systemctl 管理挂载点

### 查看和控制挂载点

```bash
# 查看挂载点状态
systemctl list-units --type=mount

# 查看特定挂载点状态
systemctl status mount-point.mount

# 挂载文件系统
systemctl start mount-point.mount

# 卸载文件系统
systemctl stop mount-point.mount

# 重新挂载文件系统
systemctl reload mount-point.mount
```

### 创建自定义挂载单元

```bash
# 创建挂载单元文件
sudo vim /etc/systemd/system/data.mount
```

示例挂载单元内容：
```ini
[Unit]
Description=Data Mount Point

[Mount]
What=/dev/sdb1
Where=/mnt/data
Type=ext4
Options=defaults,noatime

[Install]
WantedBy=multi-user.target
```

启用并挂载：
```bash
sudo systemctl daemon-reload
sudo systemctl enable data.mount --now
```

## 使用 systemd 定时器

systemd 定时器提供了比传统 cron 任务更灵活的调度机制。

### 创建定时器

1. **创建服务文件**：
   ```bash
   sudo vim /etc/systemd/system/backup.service
   ```

   内容：
   ```ini
   [Unit]
   Description=Backup Service
   
   [Service]
   Type=oneshot
   ExecStart=/usr/local/bin/backup-script.sh
   ```

2. **创建定时器文件**：
   ```bash
   sudo vim /etc/systemd/system/backup.timer
   ```

   内容：
   ```ini
   [Unit]
   Description=Run Backup Daily
   
   [Timer]
   OnCalendar=*-*-* 03:00:00  # 每天凌晨 3 点执行
   Persistent=true           # 系统启动后，如果错过执行时间则立即执行
   
   [Install]
   WantedBy=timers.target
   ```

3. **启用定时器**：
   ```bash
   sudo systemctl daemon-reload
   sudo systemctl enable backup.timer --now
   ```

### 管理定时器

```bash
# 查看所有定时器
systemctl list-timers

# 查看特定定时器状态
systemctl status backup.timer

# 启用定时器
systemctl enable timer-name.timer

# 禁用定时器
systemctl disable timer-name.timer

# 启动定时器（临时启用）
systemctl start timer-name.timer

# 停止定时器
systemctl stop timer-name.timer
```

## 高级 systemd 功能

### 资源控制（CGroup）

systemd 使用 Linux 控制组（CGroup）来管理和限制服务的资源使用。

```bash
# 修改服务的资源限制
sudo mkdir -p /etc/systemd/system/service-name.service.d/
sudo vim /etc/systemd/system/service-name.service.d/resource.conf
```

示例资源限制配置：
```ini
[Service]
# CPU 限制
CPUQuota=50%

# 内存限制
MemoryLimit=512M

# 进程数限制
TasksMax=100
```

重新加载配置：
```bash
sudo systemctl daemon-reload
sudo systemctl restart service-name
```

### 环境变量

可以为服务设置环境变量，有几种方法：

1. **直接在服务文件中设置**：
   ```ini
   [Service]
   Environment=VAR1=value1 VAR2=value2
   ```

2. **使用环境文件**：
   ```ini
   [Service]
   EnvironmentFile=/path/to/environment/file
   ```

3. **使用 systemctl 命令**：
   ```bash
   sudo systemctl set-environment VAR1=value1
   sudo systemctl unset-environment VAR1
   ```

### 安全增强

systemd 提供了多种安全功能来限制服务的权限：

```ini
[Service]
# 安全上下文设置
PrivateTmp=true            # 使用私有临时目录
ProtectSystem=full         # 保护系统文件只读
ProtectHome=true           # 保护用户主目录
NoNewPrivileges=true       # 禁止提升权限
RestrictNamespaces=true    # 限制命名空间
SystemCallFilter=~@clock  # 过滤系统调用
```

## systemd 日志管理

### 查看和管理日志

```bash
# 查看所有日志（最新的在底部）
sudo journalctl

# 查看特定服务的日志
sudo journalctl -u service-name

# 实时查看日志
sudo journalctl -f

# 查看特定用户的日志
sudo journalctl _UID=1000

# 查看特定时间段的日志
sudo journalctl --since "2023-05-01" --until "2023-05-02"

# 按优先级过滤日志
sudo journalctl -p err

# 查看日志文件大小
sudo journalctl --disk-usage

# 清理日志（保留最新的 500MB）
sudo journalctl --vacuum-size=500M

# 清理指定日期之前的日志
sudo journalctl --vacuum-time=2weeks
```

### 配置 journald

journald 配置文件位于 `/etc/systemd/journald.conf`：

```bash
sudo vim /etc/systemd/journald.conf
```

常用配置选项：
```ini
[Journal]
# 持久化日志存储
Storage=persistent

# 日志文件大小限制
SystemMaxUse=500M

# 单个日志文件最大大小
SystemMaxFileSize=100M

# 日志保留时间
MaxFileSec=1month

# 压缩日志
Compress=yes
```

## 常见问题排查

### 服务无法启动

```bash
# 查看服务详细状态和错误信息
systemctl status service-name

# 查看服务日志
sudo journalctl -u service-name --no-pager

# 检查服务文件语法
sudo systemd-analyze verify service-name.service
```

### 系统启动慢

```bash
# 查看启动时间和各个服务的启动时间
systemd-analyze blame

# 查看启动关键路径
systemd-analyze critical-chain

# 生成启动图
systemd-analyze plot > boot.svg
```

### 服务依赖问题

```bash
# 查看服务依赖图
systemd-analyze dot service-name | dot -Tsvg > service.svg

# 检查服务依赖关系
systemctl list-dependencies service-name
```

## 最佳实践

### 服务配置最佳实践

1. **使用 Type=forking 还是 Type=simple**
   - 对于传统的 fork 型服务，使用 Type=forking
   - 对于现代的前台运行服务，使用 Type=simple

2. **设置合适的 Restart 策略**
   - 对于关键服务，使用 Restart=always
   - 对于可能失败的服务，使用 Restart=on-failure
   - 对于一次性任务，使用 Restart=no

3. **设置合理的超时时间**
   ```ini
   [Service]
   TimeoutStartSec=30
   TimeoutStopSec=10
   ```

4. **添加安全限制**
   - 使用 PrivateTmp=true 隔离临时文件
   - 使用 ProtectSystem=full 保护系统文件
   - 使用 NoNewPrivileges=true 防止权限提升

### 服务管理最佳实践

1. **始终使用 systemctl 管理服务**，避免使用 service 或 init.d 脚本

2. **修改服务时使用覆盖目录**，而不是直接修改原始服务文件

3. **定期检查服务状态**，确保关键服务正常运行

4. **使用 systemd 定时器替代 cron 任务**，获得更好的集成和日志记录

5. **设置适当的资源限制**，防止单个服务消耗过多系统资源

6. **监控系统日志**，及时发现服务问题

## 总结

systemd 是 Rocky Linux 中强大的系统和服务管理器，提供了比传统 init 系统更多的功能和更好的性能。通过本教程，您学习了如何使用 systemctl 命令管理服务，如何创建和修改服务文件，如何使用 Targets 管理系统运行状态，以及如何使用定时器执行定时任务。

systemd 的设计理念包括并行启动、按需激活服务、基于依赖的服务管理等，这些特性使系统启动更快，资源利用更高效。同时，systemd 还提供了丰富的安全功能，可以限制服务的权限和资源使用，提高系统安全性。

在实际使用中，遵循最佳实践，合理配置和管理服务，不仅可以确保系统稳定运行，还可以提高系统性能和安全性。掌握 systemd 的使用，是成为一名高效的 Rocky Linux 系统管理员的必备技能。
