跳转至

10. 服务管理与进程控制

本章介绍 RHEL 9 的 systemd 服务管理、进程控制与 journal 日志管理。systemd 是 RHEL 9 的默认初始化系统与服务管理器,所有服务的启动、停止、自启配置与资源控制均通过它完成。掌握本章是后续安全加固、内核管理与性能优化的直接前提。


10.1 前提条件

  • 已完成第一阶段全部配置(第 1–9 章)。
  • 通过 SecureCRT(SSH 端口 2222)以 ops 用户、密钥认证方式登录 192.168.1.100,执行 sudo -i 切换至 root 环境。
  • EPEL 仓库已启用(第 7 章)。

10.2 systemd 基础与服务管理

10.2.1 服务生命周期管理

# 启动 / 停止 / 重启 / 重载配置
systemctl start   sshd
systemctl stop    sshd
systemctl restart sshd
systemctl reload  sshd        # 不中断进程,仅重载配置(服务需支持)

# 开机自启管理
systemctl enable  sshd        # 设置开机自启
systemctl disable sshd        # 取消开机自启
systemctl enable --now sshd   # 启用并立即启动(最常用)

# 状态查询
systemctl status   sshd       # 详细状态(含最近日志)
systemctl is-active  sshd     # 是否运行中(脚本判断用)
systemctl is-enabled sshd     # 是否开机自启

10.2.2 批量查看服务状态

# 查看所有运行中的服务
systemctl list-units --type=service --state=running

# 查看所有已失败的 unit(上线前必查)
systemctl list-units --state=failed

# 查看某服务的完整依赖关系
systemctl list-dependencies sshd

检查点

systemctl is-active sshd 返回 activesystemctl is-enabled sshd 返回 enabled


10.3 运行目标(Target)管理

systemd target 是 SysV runlevel 的现代替代,控制系统启动到哪个功能级别。

# 查看当前默认 target
systemctl get-default

# 生产服务器标准设置(命令行多用户模式,不启动图形界面)
systemctl set-default multi-user.target

# 临时切换 target(不改变默认值)
systemctl isolate multi-user.target

常用 target 对应关系:

target SysV runlevel 用途
poweroff.target 0 关机
rescue.target 1 单用户救援模式
multi-user.target 3 多用户命令行(生产标准)
graphical.target 5 图形界面
reboot.target 6 重启

生产服务器建议

生产服务器应将默认 target 设置为 multi-user.target,不运行图形界面,减少资源占用和攻击面。安装时已选择 Server with GUI 仅用于实验便利,实际部署可切换为命令行模式。


10.4 创建自定义 systemd 服务

以创建一个简单的监控脚本服务为例,演示完整流程。

10.4.1 准备脚本

tee /usr/local/bin/linuxdc-monitor.sh << 'EOF'
#!/bin/bash
# 简单系统监控示例脚本
while true; do
    echo "$(date) | Load: $(uptime | awk -F'load average:' '{print $2}')" \
      >> /var/log/linuxdc-monitor.log
    sleep 60
done
EOF

chmod +x /usr/local/bin/linuxdc-monitor.sh

10.4.2 创建 Unit 文件

tee /etc/systemd/system/linuxdc-monitor.service << 'EOF'
[Unit]
Description=LinuxDC System Monitor
Documentation=https://linuxdc.com
After=network.target
Wants=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/linuxdc-monitor.sh
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
# 安全限制
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/log

[Install]
WantedBy=multi-user.target
EOF

关键字段说明:

字段 说明
After=network.target 在网络就绪后再启动
Type=simple 主进程即服务进程(最常用类型)
Restart=on-failure 进程异常退出时自动重启
RestartSec=10 重启前等待 10 秒
NoNewPrivileges=true 禁止进程获取额外权限
ProtectSystem=strict 以只读方式挂载系统目录

10.4.3 启用并验证服务

# 重载 systemd 配置(新增或修改 unit 文件后必须执行)
systemctl daemon-reload

# 启用并启动
systemctl enable --now linuxdc-monitor

# 验证
systemctl status linuxdc-monitor
journalctl -u linuxdc-monitor -f

检查点

systemctl status linuxdc-monitor 显示 active (running)/var/log/linuxdc-monitor.log 有内容写入。

10.4.4 修改已有 Unit 文件

生产中不建议直接修改 /lib/systemd/system/ 下的原始 unit 文件(包升级会覆盖)。使用 drop-in 文件覆盖特定参数:

# 为 sshd 创建 drop-in 配置(覆盖部分参数)
systemctl edit sshd
# 编辑器打开 /etc/systemd/system/sshd.service.d/override.conf
# 示例:调整重启策略
# [Service]
# Restart=always
# RestartSec=5

10.5 进程管理

10.5.1 进程查看

# 静态快照
ps aux                              # 所有进程(BSD 风格)
ps -ef --forest                     # 树形结构,显示父子关系

# 按资源排序(快速定位问题进程)
ps aux --sort=-%cpu | head -10      # 按 CPU 使用率降序
ps aux --sort=-%mem | head -10      # 按内存使用量降序

# 按名称查找进程 PID
pgrep -l sshd
pgrep -la chronyd                   # 显示完整命令行

# 交互式监控
top                                 # 按 M 内存排序,P CPU 排序,q 退出
dnf install -y htop
htop                                # 增强版,支持鼠标操作

10.5.2 进程终止

# 优雅终止(发送 SIGTERM,进程有机会清理资源)
kill <PID>
kill -15 <PID>                      # 等同于上面

# 强制终止(发送 SIGKILL,进程无法拦截,谨慎使用)
kill -9 <PID>

# 按名称终止
pkill sshd                          # 终止所有名为 sshd 的进程
pkill -f "python3 /opt/app"         # 按完整命令行模式匹配
killall httpd                       # 终止所有同名进程

kill -9 的使用时机

kill -9 会强制终止进程而不给予清理机会,可能导致数据损坏或文件锁残留。应先尝试 kill(SIGTERM),等待数秒后若进程仍未退出再使用 kill -9

10.5.3 调整进程优先级

nice 值范围:-20(最高优先级)到 19(最低优先级),默认 0

# 以低优先级运行耗时任务(避免影响生产业务)
nice -n 15 tar -czf /backup/data.tar.gz /opt/data

# 调整正在运行进程的优先级
renice -n 10 -p <PID>               # 降低优先级(普通用户可执行)
renice -n -5 -p <PID>               # 提升优先级(需 root)

# 查看进程优先级
ps -eo pid,ni,comm --sort=ni | head -20

10.5.4 后台任务管理

# 后台运行(& 放到后台,nohup 防止 Shell 退出时终止)
nohup /opt/scripts/backup.sh > /var/log/backup.log 2>&1 &

# 查看后台任务
jobs -l

# 将后台任务调到前台
fg %1

# 将前台任务放到后台(先 Ctrl+Z 挂起,再 bg)
bg %1

10.6 journal 日志管理

RHEL 9 使用 systemd journal 作为主要日志系统,所有服务日志统一由 journald 收集。

10.6.1 查看日志

# 查看指定服务的日志
journalctl -u sshd                  # sshd 全部日志
journalctl -u sshd -f               # 实时追踪(等同于 tail -f)
journalctl -u sshd -n 50            # 最近 50 条

# 按时间过滤
journalctl --since "2025-06-01 08:00:00"
journalctl --since "1 hour ago"
journalctl --since today

# 按优先级过滤(emerg/alert/crit/err/warning/notice/info/debug)
journalctl -p err -b                # 本次启动的 error 及以上级别日志
journalctl -p warning --since "1 hour ago"

# 查看内核日志
journalctl -k                       # 等同于 dmesg
journalctl -k --since "30 min ago"

# 查看引导日志
journalctl -b                       # 本次引导
journalctl -b -1                    # 上次引导
journalctl --list-boots             # 列出所有引导记录

10.6.2 日志持久化配置

默认情况下 journal 日志存储在内存中(重启丢失),配置持久化到磁盘:

mkdir -p /var/log/journal
systemd-tmpfiles --create --prefix /var/log/journal

vim /etc/systemd/journald.conf

关键配置项:

[Journal]
Storage=persistent          # 持久化存储(auto/volatile/persistent/none)
Compress=yes                # 压缩日志
SystemMaxUse=2G             # 最大占用磁盘空间
SystemKeepFree=500M         # 至少保留的磁盘空间
MaxRetentionSec=30day       # 日志最长保留时间

应用配置:

systemctl restart systemd-journald

10.6.3 日志清理

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

# 按时间清理(保留最近 7 天)
journalctl --vacuum-time=7d

# 按大小清理(限制总大小为 500 MB)
journalctl --vacuum-size=500M

# 仅保留最近 5 个引导的日志
journalctl --vacuum-files=5

10.6.4 配置 rsyslog 转发日志

如需将日志转发到集中式日志服务器(如 ELK、Graylog):

vim /etc/rsyslog.conf

在文件末尾添加(TCP 转发更可靠):

# 转发所有日志到集中式服务器
# @@ 表示 TCP;@ 表示 UDP
*.* @@192.168.1.200:514
systemctl restart rsyslog

# 发送测试日志验证转发
logger -t linuxdc "Test log from 192.168.1.100"

生产环境建议

生产环境推荐使用 TCP(@@)而非 UDP(@)转发日志,TCP 有重传机制,日志不易丢失。集中式日志是等保合规的基本要求之一。


10.7 常见问题与排查

问题现象 排查步骤
服务启动失败 systemctl status <service> 看末尾错误;journalctl -u <service> -n 50 查详细日志
自定义服务不自启 确认执行了 systemctl enable;确认 [Install] 节中有 WantedBy=multi-user.target
daemon-reload 后服务仍未更新 确认 unit 文件语法正确:systemd-analyze verify /etc/systemd/system/<service>.service
日志磁盘占满 立即执行 journalctl --vacuum-size=200M;然后配置 SystemMaxUse
# 验证 unit 文件语法
systemd-analyze verify /etc/systemd/system/linuxdc-monitor.service

# 查看 systemd 启动耗时分析
systemd-analyze blame | head -20

10.8 实践任务

  1. 登录 linuxdc(SecureCRT 端口 2222,ops 用户,密钥认证,sudo -i 切换 root)。
  2. 查看当前失败的 unit:systemctl list-units --state=failed
  3. 将系统默认 target 改为 multi-user.target 并验证。
  4. 按照 10.4 节,完整创建并启用 linuxdc-monitor 服务,验证其运行状态。
  5. 查看 sshd 最近 1 小时的日志,并过滤出 warning 及以上级别:

    journalctl -u sshd --since "1 hour ago" -p warning
    
  6. 查看 journal 日志占用空间,配置持久化,并执行一次按时间清理。


10.9 自测问题

Q1:systemctl reloadsystemctl restart 有什么区别?

reload 向进程发送信号(通常是 SIGHUP),让其重新读取配置文件,不中断进程,连接不会中断(如 nginx reload);restart 先停止进程再重新启动,会中断连接。配置变更时优先使用 reload,仅在 reload 不支持时才使用 restart

Q2:新建 unit 文件后为什么必须执行 systemctl daemon-reload

systemd 在启动时将 unit 文件解析并缓存到内存中。新增或修改 unit 文件后,内存缓存不会自动更新。daemon-reload 命令强制 systemd 重新扫描并加载所有 unit 文件,使变更生效。

Q3:journal 日志默认重启后丢失,如何确认是否已配置持久化?

执行 ls /var/log/journal/,若目录存在且有内容,说明已持久化;若目录不存在或为空,日志仅存储在 /run/log/journal/(内存,重启丢失)。可通过 journalctl --disk-usage 查看当前占用情况。


10.10 章节总结

本章介绍了 RHEL 9 systemd 服务管理的核心操作:服务生命周期控制、运行目标管理、自定义 service unit 创建(含安全限制字段)、进程查看与终止,以及 journal 日志的查询、持久化与清理。这些是运维日常工作的高频操作,也是后续内核管理与安全加固的基础工具。