Linux进阶篇05:systemd 深度实战
环境声明VirtualBox 虚拟机Rocky Linux 9Legacy BIOS (非 UEFI)最小化安装/Server 环境。前置知识已完成《Rocky 9 启动流程》《GRUB2 深度配置》学习理解 systemd 是内核启动后第一个用户态进程PID 1。核心目标搞懂 systemd 统治一切的底层逻辑掌握 Unit 文件 [Service]/[Install] 段配置彻底分清 Typeforking 与 Typenotify 的差异能独立编写、调试自定义服务。目录一、前言为什么说 systemd 统治一切二、systemd 服务管理逻辑图解三、Unit 文件基础systemd 的宪法四、Unit 文件三段结构详解1. [Unit] 段服务的元数据与依赖2. [Service] 段服务的执行逻辑3. [Install] 段服务的开机自启配置五、核心难点Typeforking vs Typenotify1. Typeforking传统守护进程的老办法2. Typenotifysystemd 原生的新办法3. 两者核心差异对比表六、实操解析系统自带服务sshd七、实操自定义服务完整流程从 0 到 1八、systemd 服务管理常用命令Rocky 9 专属九、排障速查表systemd 服务篇十、小结一、前言为什么说 systemd “统治一切”上一章我们讲到GRUB 把控制权交给内核内核完成初始化后启动的第一个用户态程序是 /sbin/init软链接到 systemd。从这一刻起Linux 系统的所有资源服务、定时任务、硬件挂载、网络配置、登录会话全由 systemd 统一管理传统 SysVinit、upstart 早已被淘汰这也是 RHEL 7含 Rocky 9的核心变化。对我们 SRE 来说systemd 是日常运维的总控制台启动服务、查日志、设开机自启、做故障恢复全离不开它。本章不堆砌命令而是从 Unit 文件的结构入手把 systemd 的统治逻辑拆透。二、systemd 服务管理逻辑图解先搞懂 systemd 怎么管服务再看配置文件三、Unit 文件基础systemd 的宪法Unit 是 systemd 管理资源的最小单位后缀不同代表不同类型我们重点讲最常用的 .service 服务单元它的标准路径有两个Rocky 9 严格区分/usr/lib/systemd/system/系统预装/软件包安装的服务如 sshd.service不要手动改这里面的文件系统升级会被覆盖。/etc/systemd/system/用户自定义/手动修改的服务优先级高于上面的路径改服务配置、写新服务都放这里。四、Unit 文件三段结构详解拿系统自带的 sshd.service 举例想可以看到完整内容用 systemctl cat ss hd.service核心分三段1. [Unit] 段服务的元数据与依赖定义服务的描述、启动顺序、依赖关系不涉及具体执行逻辑。核心字段After/Before控制启动顺序不是依赖关系比如 Afternetwork.target 不代表 network 必须启动成功只是等我之后启动。Wants/Requires控制依赖关系Wants 是弱依赖Requires 是强依赖不建议用 Requires容易连锁故障。2. [Service] 段服务的执行逻辑定义服务怎么启动、怎么停止、怎么重启是我们配置的核心。核心字段Type启动类型本章核心后面单独讲。ExecStart启动服务的命令必须用绝对路径不能用相对路径、alias。Restart重启策略always总是重启、on-failure非 0 退出码/被信号杀死才重启、no不重启默认。PIDFile主进程 PID 文件路径Typeforking 时必须指定否则 systemd 找不到主进程。3. [Install] 段服务的开机自启配置定义服务如何关联开机启动的 Target只有 enable 服务时才会用到这段。核心逻辑systemctl enable sshd 的本质是在 /etc/systemd/system/multi-user.target.wants/ 目录下创建 sshd.service 的软链接。反过来 disable 就是删除这个软链接。注意Rocky 9 最小化安装默认启动到 multi-user.target桌面版默认到 graphical.target自定义服务一般写 WantedBymulti-user.target 即可。实操是这样的五、核心难点Typeforking vs Typenotify这是 systemd 服务配置里最容易踩坑的地方也是面试高频题我们用人话实操讲透1. Typeforking传统守护进程的老办法工作原理服务启动时父进程先 fork 出一个子进程真正干活的守护进程然后父进程主动退出。systemd 等到父进程退出后才认为服务启动完成并通过 PIDFile 指定的文件找到子进程主进程后续监控子进程状态。适用场景传统的 Unix 守护进程比如老版本 httpd、vsftpd这些程序本身就是 fork 后父进程退出的逻辑。必须配置必须指定 PIDFile/path/to/pid否则 systemd 找不到子进程会认为启动失败报Failed to read PID from file错误。一般配合 ExecStart/path/to/binary -D实操示例(明白就行不建议实操systemd root 权限太大了)先写一个会 fork 的测试脚本 /opt/fork_demo.sh#!/bin/bashecho$$/var/run/fork_demo.pid# 把当前 PID 写入 pid 文件sleepinfinity# 模拟守护进程给执行权限chmod x /opt/fork_demo.sh写 Unit 文件 /etc/systemd/system/fork-demo.serviceini [Unit] DescriptionForking Demo Service Afternetwork.target [Service] Typeforking ExecStart/opt/fork_demo.sh PIDFile/var/run/fork_demo.pid Restarton-failure [Install] WantedBymulti-user.target加载配置并启动systemctl daemon-reload systemctl start fork-demo查看状态systemctl status fork-demo → 显示 active (running)主进程 PID 和 pid 文件里的一致。如果不写 PIDFile启动会报Failed to parse PID from file /var/run/fork-demo.pid: Invalid argument或者一直卡在启动中直到超时。2. Typenotifysystemd 原生的新办法工作原理服务启动后主动给 systemd 发送一个 READY1 的通知信号通过 sd_notify() 系统调用systemd 收到这个信号后才认为服务启动完成。不需要依赖 PID 文件也不需要父进程退出。适用场景原生支持 systemd 的服务比如 Rocky 9 里的 sshd、nginx、redis 新版本是目前最推荐的 Type。必须配置服务程序本身要支持发送 sd_notify 信号大部分现代服务都支持比如 sshd 默认就支持 notify。不需要 PIDFilesystemd 能直接拿到主进程 PID。实操示例自定义 notify 服务用 systemd 自带的 systemd-notify 命令发送通知写脚本 /opt/notify_demo.sh#!/bin/bash# 模拟服务初始化过程比如加载配置、连数据库sleep5# 给 systemd 发送就绪信号systemd-notify--ready--statusDemo service initialized# 模拟守护进程sleepinfinity给执行权限chmod x /opt/notify_demo.sh写 Unit 文件 /etc/systemd/system/notify-demo.serviceini [Unit] DescriptionNotify Demo Service Afternetwork.target [Service] Typenotify ExecStart/opt/notify_demo.sh Restarton-failure # 可选限制服务启动超时时间默认 90 秒没收到 notify 信号就认为启动失败 TimeoutStartSec30s [Install] WantedBymulti-user.target加载配置并启动systemctl daemon-reload systemctl start notify-demo查看状态systemctl status notify-demo → 5 秒后状态从 activating (start) 变为 active (running)说明收到了 notify 信号。优势比 forking 更可靠如果服务初始化卡住比如连不上数据库超过 TimeoutStartSec 还没发 notify 信号systemd 会直接判定启动失败不会像 forking 那样傻等父进程退出。3. 两者核心差异对比表六、实操解析系统自带服务sshd用系统自带的 sshd 验证上面的知识加深理解# 查看 sshd 的 Unit 文件systemctlcatsshd.service# 查看 sshd 的服务状态systemctl status sshd# 查看 sshd 的依赖关系systemctl list-dependencies sshd.service# 查看 sshd 的开机自启状态systemctl is-enabled sshd你会发现 Rocky 9 的 sshd 默认 Typenotify这就是现代服务的标准配置。七、实操自定义服务完整流程从 0 到 1我们写一个打印时间戳到文件的自定义服务巩固全流程写服务脚本 /opt/time_logger.sh#!/bin/bashwhiletrue;doecho[$(date)] Service is running.../var/log/time_logger.logsleep5done给执行权限chmod x /opt/time_logger.sh写 Unit 文件 /etc/systemd/system/time-logger.serviceini [Unit] DescriptionTime Logger Service Afternetwork.target [Service] Typesimple # 简单类型ExecStart 启动的进程就是主进程不 fork 不 notify适合脚本类服务 ExecStart/opt/time_logger.sh Restartalways # 不管什么原因退出都自动重启 Userroot # 以 root 身份运行 StandardOutputjournal # 输出重定向到 journald 日志 StandardErrorjournal [Install] WantedBymulti-user.target注Typesimple 是脚本类服务最常用的类型比 forking/notify 简单只要 ExecStart 启动的进程不退就认为是运行中加载配置systemctl daemon-reload启动服务systemctl start time-logger查看日志journalctl -u time-logger -f-f 实时跟踪日志设置开机自启systemctl enable time-logger验证开机自启reboot 后执行 systemctl status time-logger确认自动启动。八、systemd 服务管理常用命令Rocky 9 专属九、排障速查表systemd 服务篇十、小结systemd 是核心从启动到服务、日志、定时任务全由 systemd 管理Unit 文件是它的宪法。Unit 三段结构[Unit] 管描述和依赖[Service] 管执行逻辑Type 是核心[Install] 管开机自启。Type 选型优先级脚本类服务用 Typesimple现代支持 systemd 的服务用 Typenotify老派传统守护进程才用 Typeforking且必须配 PIDFile。避坑铁律改 Unit 文件必执行 systemctl daemon-reload自定义服务放 /etc/systemd/system/查问题先看 journalctl -u 服务名。

相关新闻