grains.items 查全部键值对,grains.item 仅查单个键(如 cpu_model);误用后者查全部会报 valueerror;硬件键含 num_cpus、mem_total、cpu_model、disks 等;/etc/salt/grains 需严格 yaml 格式,修改后必须重启 salt-minion。

grains.items 和 grains.item 别混用,查键前先确认命令语义
想看一台 minion 有哪些硬件信息,直接跑 grains.items;只查某一项(比如 CPU 型号),必须用 grains.item cpu_model。误用 grains.item 查全部会报 ValueError: No such key,因为它的设计就是单键查询——它不支持通配或省略参数。
常见硬件相关键包括:num_cpus(整数)、mem_total(单位 MB)、cpu_model、disks(设备名列表,如 ['sda', 'nvme0n1'])、osfullname、kernelrelease。注意 disks 是列表,不是容量数据;要查磁盘使用率得调 disk.usage 模块。
/etc/salt/grains 文件必须严格 YAML 格式,改完要重启 minion
手动加自定义标识(比如 gpu: true 或 rack_id: "r07b")时,YAML 的缩进和冒号后空格是硬性要求。写成 gpu:true、- gpu: yes 或顶格无缩进,都会让 minion 启动失败,日志里出现 yaml.scanner.ScannerError。
- 正确写法:每行 key 后跟冒号+空格,值顶格对齐,布尔值用小写
true/false - 修改后必须执行
systemctl restart salt-minion(或对应 init 方式),grains 才会重加载 - 别指望热更新——grains 是启动快照,没有运行时持久化机制
-G 匹配失败?先看类型是否一致,再考虑用复合匹配
salt -G "num_cpus:8" state.apply webserver 看似合理,但若某台机器的 num_cpus 是字符串 "8"(旧系统常见),另一台是整数 8(新系统默认),-G 就会漏掉一半——Salt 的 -G 是严格类型匹配。
更稳的做法:
- 用通配符:
salt -G "num_cpus:*8*" state.apply webserver - 在 state 或 pillar 中统一转字符串:
{{ grains['num_cpus']|string }} - 匹配列表字段(如
disks)不能直接-G "disks:nvme0n1",得切到复合匹配:salt -C "G@disks:*nvme0n1*"
grains.setval 是临时操作,不写磁盘也不持久
grains.setval gpu True 确实能立刻生效,但它只存在当前 minion 进程内存里。一旦重启、服务崩溃或被 kill,值就丢了。它也不会写入 /etc/salt/grains,master 无法通过 salt '*' grains.items 持久看到这个变更。
真正批量设值的路径只有两条:
- 在 minion 端用
file.managed推送 YAML 格式的/etc/salt/grains,再重启服务 - 在 master 端用
salt '*' grains.setval gpu=True——但注意:这仍只是内存操作,且需要 minion 本机 root 权限,不推荐用于生产环境的长期标记
最常被忽略的一点:自定义 grains 脚本(放在 _grains/ 目录下)如果没清理干净,和配置文件里的同名 key 冲突,结果可能被意外覆盖——建议每次 sync_grains 前检查 _grains 目录是否为空。











