2. RHEL系统管理基础回顾

在进入 Ansible、SaltStack 等自动化工具之前,必须先回到 RHEL 系统本身,把四类基础管理对象——服务、网络、软件包、用户与权限——的“真实操作入口”梳理清楚。自动化工具本质上只是把这些手工命令封装成可重复、可批量、可审计的模块。如果对底层命令、配置文件位置、状态判断方式没有统一认知,写出来的 Playbook 或 State 文件往往只能“看起来能跑”,一旦失败就无从排查。本节不追求覆盖全部参数,而是围绕“自动化会调用什么、返回什么、如何判断成功”这条主线,把四块基础重新对齐。

一、systemd 服务管理:从 unit 到运行状态

RHEL 7 之后,systemd 取代 SysV init 成为 PID 1,服务管理的核心对象是 unit。自动化中最常操作的是 .service 类型,此外还有 .socket、.target、.timer。理解 unit 的关键在于区分三个维度:是否开机自启(enabled/disabled)、当前是否运行(active/inactive)、运行结果是否正常(active (running) / failed)。这三者互相独立,例如一个服务可以 enabled 但当前 inactive,也可以 active 但 disabled。

systemctl status sshd
systemctl is-enabled sshd      # enabled / disabled
systemctl is-active sshd       # active / inactive / failed
systemctl enable --now sshd    # 开机自启并立即启动
systemctl list-units --type=service --state=failed

自动化模块(如 Ansible 的 service / systemd 模块)最终就是调用上述语义。判断一个服务是否“配置成功”,不能只看命令返回码,还要看 is-active 与 is-enabled 的组合是否符合预期。若服务启动失败,应通过 systemctl status 与 journalctl -u 服务名 查看退出码和日志,而不是反复重试。

二、网络配置:从 ifcfg 到 NetworkManager

RHEL 8/9 默认使用 NetworkManager 管理网络,但传统 ifcfg-* 文件仍被兼容。自动化场景下,推荐使用 nmcli 或 nmstate,因为它们提供结构化输出,便于幂等判断。核心参数包括:IP 地址与掩码、网关、DNS、连接名(connection name)与设备名(device)。注意“连接”与“设备”是两个概念:一个设备可以挂多个连接配置,但同一时刻只有一个处于 activated 状态。

nmcli connection show
nmcli device status
nmcli connection modify ens160 ipv4.addresses 192.168.10.20/24 \
  ipv4.gateway 192.168.10.1 ipv4.dns 192.168.10.1 ipv4.method manual
nmcli connection up ens160

自动化中常见的坑是:只改了配置文件却没有 up 连接,或者改了 ifcfg 但 NetworkManager 未重载。判断网络是否生效,应同时检查 ip addr、ip route 与 nmcli connection show --active,三者一致才算真正生效。

三、软件包管理:dnf 与仓库体系

RHEL 8/9 使用 dnf 作为包管理器,底层仍是 RPM。自动化安装软件包时,关键不只是“装上了”,还要保证仓库可用、版本可控、依赖可解析。仓库定义位于 /etc/yum.repos.d/*.repo,每个仓库包含 baseurl、enabled、gpgcheck 等字段。若仓库不可达,dnf install 会直接失败,而不是静默跳过。

dnf repolist
dnf list installed httpd
dnf install -y httpd
dnf module list nginx        # 模块化流,RHEL 8+ 特有
rpm -q httpd                 # 查询已安装版本

自动化模块(如 dnf 模块)通常支持 state: present/absent/latest。需要特别注意的是 latest 会触发升级,可能引入非预期变更;生产环境更推荐锁定版本或使用模块流。判断安装结果时,应结合 rpm -q 与 dnf list installed,而不是仅依赖命令退出码。

四、用户与权限模型:UID、GID 与 sudo

RHEL 的用户权限模型由三部分组成:账户(/etc/passwd、/etc/shadow)、组(/etc/group、/etc/gshadow)、权限位与 ACL。自动化创建用户时,必须明确 UID/GID 是否固定、家目录是否创建、登录 shell 是什么、是否加入附加组。UID 若在不同主机上不一致,会导致共享存储上的文件属主错乱,因此批量环境中通常要求统一规划 UID。

useradd -u 1500 -G wheel -m -s /bin/bash deploy
echo 'deploy:Str0ngP@ss' | chpasswd
id deploy
usermod -aG docker deploy
visudo   # 编辑 /etc/sudoers,推荐用 /etc/sudoers.d/ 片段

权限方面,除了 chmod/chown,还应了解 setfacl/getfacl 用于精细化授权。自动化中判断用户是否配置正确,应检查 id 用户名 输出的 uid、gid、groups 三部分,以及 sudo -l -U 用户名 的授权结果。

RHEL 四类基础管理对象与自动化调用关系 systemd 服务 unit / enabled / active systemctl · journalctl 判断:is-active + is-enabled 网络配置 connection / device nmcli · ifcfg · nmstate 判断:ip addr + route + active 软件包管理 repo / rpm / module dnf · rpm 判断:rpm -q + repolist 用户与权限 uid / gid / acl / sudo useradd · chmod · setfacl 判断:id + sudo -l 自动化模块统一调用层 Ansible / SaltStack / 脚本封装 幂等判断:期望状态 vs 实际状态 changed / ok / failed 三态反馈 状态一致 → ok / changed 状态不一致 → failed 排查

五、四类对象的统一认知:状态、幂等与判断依据

把上面四块放在一起看,会发现它们共享同一套自动化思维:先定义期望状态,再读取实际状态,最后比较差异并决定是否变更。服务关注 enabled/active,网络关注 connection 是否 activated,软件包关注是否 installed 及版本,用户关注 uid/gid/组/权限是否匹配。自动化工具返回的 changed、ok、failed 三态,正是这套比较逻辑的外在表现。

因此,在编写任何自动化任务前,建议先手工执行一遍对应命令,记录下“正常状态长什么样”。例如:

管理对象期望状态示例实际状态检查命令不一致时的典型原因
systemd 服务sshd enabled + activesystemctl is-enabled/is-active sshdunit 未 enable、端口被占用、配置语法错误
网络连接ens160 使用静态 IP 且 activatednmcli connection show --active连接未 up、IP 冲突、网关不可达
软件包httpd 已安装且版本符合rpm -q httpd仓库不可用、依赖冲突、模块流未启用
用户与权限deploy uid=1500 且属于 wheelid deployUID 冲突、组未创建、sudoers 片段未生效
自动化不是“替代手工”,而是“把手工验证过的正确状态固化下来”。先手工跑通,再写成模块,是避免批量故障最有效的方法。
批量修改网络或 sudoers 时,务必保留一个已登录的会话或带外管理通道。一旦配置错误导致 SSH 中断,自动化任务本身无法自救。