10 - 服务管理与进程控制(systemd)
前提条件
- 已完成第一阶段所有内容(基础部署、apt 源、SSH 安全加固、fail2ban 等)
- 以 root 身份登录,或 ops 用户执行
sudo -i切换至 root 环境 - 系统运行在 Debian 12 Bookworm,SSH 端口已改为 2222
- 虚拟机环境:VMware Workstation Pro
全局参数
主机名 linuxdc,IP 192.168.1.100/24,SSH 端口 2222,运维用户 ops
详细步骤
1. systemd 核心概念速览
| 单元类型 | 说明 | 典型示例 |
|---|---|---|
service |
最常见的服务单元 | ssh.service、nginx.service |
target |
服务组,类似运行级别 | multi-user.target(相当于 runlevel 3) |
timer |
定时任务,替代传统 cron | unattended-upgrades.timer |
socket |
按需激活服务 | docker.socket |
mount |
挂载点管理 | /etc/systemd/system/mnt-data.mount |
2. 查看系统和服务状态
systemctl status # 当前 target 和整体状态
systemctl get-default # 默认运行级别(通常 multi-user.target)
systemctl list-units --type=service --state=running # 列出所有运行中的服务
systemctl list-unit-files --type=service | grep enabled # 列出所有已启用的服务
3. 服务基本操作
# 以 ssh 为例(以下命令均以 root 身份执行)
systemctl status ssh
systemctl start ssh # 启动
systemctl stop ssh # 停止
systemctl restart ssh # 重启(中断现有连接)
systemctl reload ssh # 平滑重载配置(不中断已有连接)
systemctl enable ssh # 设置开机自启(创建符号链接)
systemctl disable ssh # 取消开机自启
# 屏蔽服务(防止被意外启动,优先级高于 enable)
systemctl mask avahi-daemon
systemctl unmask avahi-daemon
注意
在虚拟机内操作时,systemctl stop ssh 会断开当前 SSH 连接。建议通过 VMware 控制台执行,或立即跟上 systemctl start ssh。
4. 日志查看与实时跟踪(journalctl)
journalctl -u ssh -n 200 # ssh 最近 200 行日志
journalctl -u ssh -f # 实时跟踪(Ctrl+C 退出)
journalctl -u ssh --since "today" # 今天的所有 ssh 日志
journalctl -b -p warning..emerg # 本次启动的警告及以上级别日志
journalctl --disk-usage # 查看日志磁盘占用
journalctl -b -1 -p err # 上次启动的错误日志
日志级别参考:emerg(0) > alert(1) > crit(2) > err(3) > warning(4) > notice(5) > info(6) > debug(7)
5. 创建自定义 systemd 服务
示例:创建一个后台持续运行的日志脚本服务。
创建脚本:
mkdir -p /opt/testservice
vim /opt/testservice/hello.sh
脚本内容:
#!/bin/bash
while true; do
echo "$(date '+%Y-%m-%d %H:%M:%S') - Hello from systemd service"
sleep 60
done
赋予执行权限:
chmod +x /opt/testservice/hello.sh
创建服务单元文件:
vim /etc/systemd/system/hello.service
内容:
[Unit]
Description=Simple Hello World Service
After=network.target
[Service]
Type=simple
ExecStart=/opt/testservice/hello.sh
Restart=always
RestartSec=5
User=ops
StandardOutput=append:/var/log/hello.log
StandardError=append:/var/log/hello.log
[Install]
WantedBy=multi-user.target
加载、启动、验证:
systemctl daemon-reload
systemctl enable hello
systemctl start hello
systemctl status hello
tail -f /var/log/hello.log
检查点
systemctl status hello 显示 active (running),tail -f /var/log/hello.log 每 60 秒追加一行带时间戳的输出。
6. 日志清理与维护
journalctl --vacuum-time=30d # 删除 30 天前的日志
journalctl --vacuum-size=500M # 将日志总大小压缩至 500 MB 以内
systemctl reset-failed # 清除所有 failed 状态单元
systemctl reset-failed hello # 清除指定服务的 failed 状态
实践任务
- 查看当前系统所有运行中的服务,找出内存占用最高的前 5 个(提示:
systemd-cgtop) - 临时停止 ssh 服务,再启动,确认 2222 端口恢复监听(
ss -tuln | grep 2222) - 创建上述
hello.service示例服务,启用开机自启,验证日志是否正常写入 - 用
journalctl -u hello -f实时观察服务输出
自测问题
1. systemctl enable 和 systemctl start 的区别是什么?
systemctl start 是立即启动服务,效果仅限当前运行时,重启后若未 enable 则不会自动启动。systemctl enable 是设置开机自启,在 /etc/systemd/system/ 下对应的 .wants/ 目录中创建符号链接,下次启动时 systemd 会自动拉起该服务,但不影响当前运行状态。生产环境通常组合使用:systemctl enable --now ssh(同时设置自启并立即启动)。
2. 如何让服务在网络完全就绪后再启动?
在单元文件的 [Unit] 段中添加:
After=network-online.target
Wants=network-online.target
network.target 仅表示网络配置已应用,不代表网络实际连通;network-online.target 会等待 systemd-networkd-wait-online 确认网络接口真正在线后才触发依赖服务,适合需要在启动时访问外网的服务(如 VPN 客户端、动态 DNS 更新脚本)。
3. journalctl -b -p err 显示的是什么内容?
显示本次系统启动以来,优先级为 err(3)及以上(即 err、crit、alert、emerg)的所有日志条目。这是排查启动问题和服务崩溃的常用命令。-b -1 可查看上次启动的日志,适合排查崩溃重启后的问题根因。
4. 如果一个服务配置了 Restart=always,如何临时停止而不删除文件?
直接 systemctl stop 后,systemd 会检测到服务退出并按 RestartSec 间隔再次拉起。要真正临时停止,需使用 mask:
systemctl mask hello # 屏蔽服务(阻止任何方式启动)
systemctl stop hello # 停止当前运行实例
# 恢复时
systemctl unmask hello
systemctl start hello
或先 disable 再 stop(下次重启后不会自启,但当前仍不会被 systemd 自动拉起):
systemctl disable hello
systemctl stop hello
总结
systemd 是 Debian 现代运维的核心,掌握服务状态查看、启动控制、日志追踪和自定义单元是后续所有服务类章节的基础。生产环境中,优先使用 systemctl + journalctl 排查问题,而不是旧的 service 命令或直接翻阅 /var/log 下的文本日志。