☰
Salt 硬件探测实战指南:devinfo 执行模块的 `filter` 与 `hwinfo` 用法详解
2026/10/11 6:03:21 网站建设 项目流程
  • 运维
  • 配置管理
  • 后端

【免费下载链接】salt

Software to automate the management and configuration of infrastructure and applications at scale.

项目地址:https://gitcode.com/gh_mirrors/sa/salt
点击查看免费下载

本指南面向希望在 Salt 中快速探测目标机器硬件信息、并按 udev 属性筛选磁盘设备的运维与平台工程师。文章围绕 Salt 官方文档中devinfo模块(doc/ref/modules/all/salt.modules.devinfo.rst,其内容由 salt/modules/devinfo.py 承载)展开,介绍devinfo.filter与devinfo.hwinfo两个公开执行函数的全部参数、CLI 用法与返回值结构,并结合模块源码与单元测试(tests/pytests/unit/modules/test_devinfo.py)解释其底层实现,使读者读完能直接写出可用的硬件筛选与探测命令。

模块概述与适用平台

devinfo是 Salt 的硬件信息探测执行模块,通过执行系统自带的hwinfo与udevadm命令,将硬件信息转化为结构化字典返回给 Salt 调用方。从 salt/modules/devinfo.py 的模块头可以看到:

  • maintainer:Alberto Planas(aplanas@suse.com)
  • maturity:new(较新的模块)
  • depends:None(模块本身无硬性依赖,但依赖系统存在hwinfo命令)
  • platform:Linux

因此devinfo只在 Linux 平台生效,且在目标 minion 上需要安装hwinfo软件包(openSUSE、SUSE Linux Enterprise 与主流 Linux 发行版均提供该命令)。模块内部实际通过 salt.modules.cmdmod 调用外部命令,底层证据可见 salt/modules/devinfo.py 中cmd.run_stdout(cmd)的执行方式。

模块共暴露两个公开执行函数:

函数作用依赖
devinfo.filter按 udev 键值对筛选磁盘设备disksgrain 与udev.info执行模块
devinfo.hwinfo探测并汇总 BIOS/CPU/磁盘/内存/网络/分区等硬件信息系统hwinfo命令

注意 salt/modules/devinfo.py 中的__func_alias__把内部函数filter_对外映射为filter,所以在 Salt 命令行与状态文件里使用的是devinfo.filter而非devinfo.filter_。

devinfo.filter:按 udev 属性筛选磁盘设备

功能与 CLI 用法

devinfo.filter返回一张按 udev 键值过滤后的设备列表:返回的设备必须匹配udev_in中声明的键值,且不匹配udev_ex中声明的键值。官方 CLI 示例如下:

salt '*' devinfo.filter udev_in='{"e.id_bus": "ata"}'

上面的命令会返回所有挂在 ATA 总线上的磁盘设备。从 tests/pytests/unit/modules/test_devinfo.py 的test_devices用例可以印证筛选行为:

  • udev_in={"e.id_bus": "ata"}时返回["sda", "sr0"](硬盘与光驱均属于 ata 总线);
  • udev_in={"e.id_bus": "usb"}时返回["sdb"];
  • udev_in={"e.id_bus": "ata"}且udev_ex={"s": ["cdrom"]}时返回["sda"],说明排除了属于 cdrom 的sr0。

参数说明

参数类型含义
udev_indict设备 udev 信息中预期匹配的key: value字典,未传时视为{}
udev_exdict设备 udev 信息中不允许出现的key: value字典(排除条件),未传时视为{}

udev_in/udev_ex中的 key 是小写、以点连接的字符串,表示设备 udev 信息字典中的一条路径。例如e.id_bus对应udev['E']['ID_BUS']。如果设备 udev 信息中某个值本身是列表,算法会检查"至少有一项与参数值中的某一项相同"。

键路径解析原理:_udev

点分键的解析由内部函数_udev完成,见 salt/modules/devinfo.py:key.partition(".")每次只取最前一段,将其转为大写后到当前层字典中取值,再对剩余部分递归;键为空时直接返回整棵字典;路径中断或值不是字典时返回字符串"n/a"。单元测试 tests/pytests/unit/modules/test_devinfo.py 覆盖了这些分支:

assert devinfo._udev({"A": {"B": 1}}, "a.b") == 1 assert devinfo._udev({"A": {"B": 1}}, "A.B") == 1 assert devinfo._udev({"A": {"B": 1}}, "a.c") == "n/a" assert devinfo._udev({"A": [1, 2]}, "a.b") == "n/a" assert devinfo._udev({"A": {"B": 1}}, "") == {"A": {"B": 1}}

匹配规则原理:_match

_match(salt/modules/devinfo.py)把匹配条件与设备值分别转为集合后求交集:只要存在交集即视为命中(res = res and (value & udev_value))。若取到的设备值是字典(说明键路径未落到叶子节点),会记录一条 warning 日志并跳过该项匹配。对应测试见 tests/pytests/unit/modules/test_devinfo.py。

完整执行流程

filter_的实现(salt/modules/devinfo.py)分为四步:

  1. 从__grains__["disks"]拿到本机全部磁盘设备名(该 grain 由核心 grain 模块 salt/grains/core.py 在 minion 启动时收集);
  2. 对每个设备调用__salt__"udev.info"获取一次 udev 信息,缓存在udev_info字典中;
  3. 分别计算满足udev_in的设备集合与满足udev_ex的设备集合;
  4. 返回sorted(udev_in 集合 - udev_ex 集合),即匹配且未被排除的设备的有序列表。

其中udev.info来自 salt/modules/udev.py,内部执行udevadm info --export --query=all,把E:前缀的行解析为环境变量子字典(E键),其余行按前缀归并为列表,返回结构形如{"S": [...], "E": {"ID_BUS": "ata", ...}}。这正是点分键中e.前缀与s.前缀对应的来源。

devinfo.hwinfo:探测并汇总硬件信息

功能与 CLI 用法

devinfo.hwinfo调用系统hwinfo命令探测硬件,并把输出解析为结构化字典。官方 CLI 示例如下:

salt '*' devinfo.hwinfo salt '*' devinfo.hwinfo items='["disk"]' short=no salt '*' devinfo.hwinfo items='["disk"]' short=no devices='["/dev/sda"]' salt '*' devinfo.hwinfo devices=/dev/sda

devices参数既支持列表('["/dev/sda"]')也支持单个字符串(/dev/sda)。

参数说明

参数类型默认值含义
itemslist/tuple/str['bios', 'cpu', 'disk', 'memory', 'network', 'partition']要探测的硬件项列表,每项对应hwinfo --<item>
shortboolTrue只显示摘要;short=no时输出完整详情
listmdboolFalse是否同时报告 RAID 设备(映射为hwinfo --listmd)
deviceslist/tuple/strNone只显示指定设备的信息(映射为hwinfo --only <device>)

若传入的items不是 list/tuple,源码会先包装成单元素列表(salt/modules/devinfo.py),devices同理,因此单值字符串也能直接使用。

命令构造与执行

hwinfo函数(salt/modules/devinfo.py)按如下方式构造命令:

cmd = ["hwinfo"] for item in items: cmd.append(f"--{item}") if short: cmd.append("--short") if listmd: cmd.append("--listmd") for device in devices: cmd.append(f"--only {device}")

随后通过__salt__"cmd.run_stdout"执行(底层是 salt.modules.cmdmod.run_stdout 的封装),再调用_hwinfo_parse把输出解析成字典存入result["hwinfo"]。

返回值结构

hwinfo的返回值由解析结果与三类 grain 汇总组成:

  • result["hwinfo"]:hwinfo命令解析后的结构化数据;
  • 当items含bios时,附加result["bios grains"] = {"efi": ..., "efi-secure-boot": ...}(取自__grains__["efi"]与__grains__["efi-secure-boot"]);
  • 当items含memory时,附加result["memory grains"] = {"mem_total": ...}(取自__grains__["mem_total"]);
  • 当items含network时,附加result["network grains"],包含fqdn、ip_interfaces,非short模式还包含dns。

上述三个 grain 均在核心 grain 模块 salt/grains/core.py 中收集(mem_total见该文件第 699–703 行附近的mem_data,ip_interfaces见ip_interfaces()函数),因此devinfo.hwinfo相当于"系统hwinfo命令 + Salt 核心 grains"的组合视图。

摘要模式解析:_hwinfo_parse_short

当short=True(默认)时使用_hwinfo_parse_short(salt/modules/devinfo.py)解析。它以缩进区分层级:

  • 缩进 4 个空格的续行归入上一个条目,并作为无序子项存入current_result;
  • 缩进 2 个空格的key value行解析为键值对;
  • 以冒号结尾的key:行开启新的硬件段,值为空字典。

例如 tests/pytests/unit/modules/test_devinfo.py 中的摘要输出会被解析为{"cpu": {0: "...", 1: "..."}, "disk": {"/dev/fd0": "Disk", "/dev/sda": "QEMU HARDDISK"}, ...}这样的结构,其中无键名的多行条目依次使用递增整数作为键。

完整模式解析:_hwinfo_parse_full

当short=no时使用_hwinfo_parse_full(salt/modules/devinfo.py),把hwinfo的完整报告解析为多级嵌套字典。其核心规则包括:

  • 以行首空格数决定层级(level与缩进深度保持一致);
  • 顶层NN: <描述>行创建段落,并把冒号后的首个子元素解析为key: value;
  • [Created at ...]或无法解析的行落入当前段的Note键;
  • I/O Port键统一改名为I/O Ports;
  • Config Status的a=b, c=d形式解析为嵌套字典;
  • Driver、Driver Modules去除引号并按,拆成列表;Tags、Device Files、Features按逗号拆成列表;
  • 键冲突时自动把多个值合并为列表(如多个I/O Ports、多个Memory Range、多个Size);
  • 以#开头的行视为新段落,如Handle、BIOS Info、System Info等段落会各自成为嵌套字典;
  • 光盘的El Torito info被特殊解析为{"platform": ..., "bootable": "yes"/"no", ...}字典。

这些行为在测试中均有详尽断言,例如 tests/pytests/unit/modules/test_devinfo.py 对含光驱、软盘、硬盘三种存储设备的hwinfo --disk输出验证:Device Files、Features被解析为列表,El Torito info被解析为嵌套字典;tests/pytests/unit/modules/test_devinfo.py 验证了I/O Ports的列表合并与Config Status的字典化;tests/pytests/unit/modules/test_devinfo.py 验证了网卡段Attached to被解析为{"Handle": ...}。

典型实战场景

场景一:列出全部 ATA/SATA 磁盘

salt '*' devinfo.filter udev_in='{"e.id_bus": "ata"}'

结合 tests/pytests/unit/modules/test_devinfo.py 的行为,可预期返回该主机上所有 ata 总线磁盘(含光驱等块设备)的有序列表。若只想保留硬盘、排除光驱,可追加排除条件:

salt '*' devinfo.filter udev_in='{"e.id_bus": "ata"}' udev_ex='{"s": ["cdrom"]}'

场景二:按总线类型做设备分组与装机核对

利用udev_in的列表匹配语义(设备值与参数值任一交集即命中),可以一次筛选多种总线:

salt '*' devinfo.filter udev_in='{"e.id_bus": ["usb", "nvme"]}'

该命令可用于装机后的硬件核对,确认 USB 存储与 NVMe 盘是否如预期出现。

场景三:定向探测某块磁盘的完整硬件详情

salt '*' devinfo.hwinfo items='["disk"]' short=no devices='["/dev/sda"]'

只探测disk项、输出完整模式,并限定/dev/sda,返回值中的hwinfo键会包含该盘的型号、序列号、容量、设备文件别名、驱动等信息,适合在更换硬件或扩容前做详细备案。

场景四:快速获取主机整体硬件摘要

salt '*' devinfo.hwinfo

默认探测bios/cpu/disk/memory/network/partition六项并输出摘要,同时附上bios grains、memory grains、network grains三个汇总段,适合做节点健康巡检的第一步。

依赖与使用前提

  • 目标 minion 必须运行 Linux 且安装hwinfo命令,否则cmd.run_stdout执行失败;
  • devinfo.filter依赖disksgrain(minion 启动时收集,见 salt/grains/core.py)以及udev.info执行模块;后者要求系统安装udevadm(salt/modules/udev.py 的__virtual__会检查udevadm是否存在);
  • hwinfo的输出格式可能因发行版/版本略有差异,_hwinfo_parse_full对异常行会记录 error 日志并跳过,解析器的健壮性已由 tests/pytests/unit/modules/test_devinfo.py 中覆盖软盘、BIOS、系统、PCI 桥、以太网、存储、显卡、网络、磁盘、键盘、鼠标、CPU、网卡等十余种hwinfo段的测试验证。

结语

devinfo是 Salt 中把系统级硬件探测命令接入统一执行模块接口的典型实现:devinfo.filter用一套简洁的点分键约定复用udev.info的结构化数据,devinfo.hwinfo则在hwinfo文本输出之上提供摘要/完整两档解析并把常用核心 grains 一并汇总。结合 salt/modules/devinfo.py 源码与 tests/pytests/unit/modules/test_devinfo.py 单元测试,你可以放心地将上述命令用于资产盘点、装机核验与硬件巡检等场景;若需了解其数据来源,可进一步阅读 salt/modules/udev.py 与 salt/grains/core.py。

  • 运维
  • 配置管理
  • 后端

【免费下载链接】salt

Software to automate the management and configuration of infrastructure and applications at scale.

项目地址:https://gitcode.com/gh_mirrors/sa/salt
点击查看免费下载
上一篇:EchoMusic私人FM个性化电台解析:推荐池切换与听歌偏好如何发现你的好音乐
下一篇:CTF 流量分析实战:WIFI 802.11 认证机制与 WPA-PSK 握手包破解

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询