Ansible遍历ansible_devices时如何配置when条件匹配子串排除loop设备
需求背景
在Ansible磁盘设备巡检任务中,需要遍历ansible_devices字典,仅处理sda类块设备、排除loop回环设备。目前已编写的两个when校验逻辑可正常生效:
- 校验设备的
partitions字段为字典(映射)类型 - 校验目标设备的
partitions字段长度为0(即无分区的裸设备)
但在新增“排除设备键名包含loop的回环设备”的校验逻辑时,反复踩坑导致逻辑失效或任务报错,始终无法实现预期筛选效果。
实际踩过的无效/报错写法
- 直接对
ansible_devices[item]存储的设备属性字典使用search字符串过滤器:直接触发类型错误,过滤器提示期望传入字符串类对象,实际拿到了整个设备的属性字典 - 编写“loop in 设备对象”的包含判断:判断逻辑无匹配效果,遍历过程中依然会输出loop设备的提示信息
- 对整个设备属性字典直接套用
match/search过滤器:判断逻辑完全失效,无法拦截loop类设备 - 尝试通过
dict2items将ansible_devices转成列表遍历、访问item.key的写法:触发YAML映射语法错误,任务完全无法正常运行
可落地的正确实现方案
核心问题根源:所有字符串匹配类的过滤器,入参必须是字符串类型,之前的写法普遍错把设备属性字典这类复杂对象传给了字符串过滤器,自然会报错或者匹配失效。
针对两种常用的遍历写法,提供可直接复用的实现:
写法1:兼容原有with_items遍历键名的模式
如果原有任务是通过with_items遍历ansible_devices的键名(item本身就是字符串类型的设备名,比如sda、loop0),不需要额外取设备对象做匹配,直接对item本身做字符串判断即可:
- name: 筛选无分区的目标块设备 debug: msg: "命中待处理设备:{{ item }}" with_items: "{{ ansible_devices.keys() }}" when: # 原有正常生效的两个校验逻辑 - ansible_devices[item].partitions is mapping - ansible_devices[item].partitions | length == 0 # 新增排除loop设备的判断,直接对字符串类型的item做匹配 - not (item is search('loop'))
常见报错诱因:如果之前错误把
with_items的取值写成"{{ ansible_devices }}"(直接遍历整个字典),此时拿到的item是整个设备的属性字典,不是字符串类型的设备名,直接对item做字符串匹配必然触发类型错误。
写法2:使用dict2items的推荐遍历模式
如果是按照Ansible规范使用dict2items做字典遍历,之前触发YAML语法错误一般是因为缩进或表达式写法不规范,正确实现如下:
- name: 筛选无分区的目标块设备 debug: msg: "命中待处理设备:{{ item.key }}" loop: "{{ ansible_devices | dict2items }}" when: # 原有正常生效的两个校验逻辑,通过item.value访问设备属性 - item.value.partitions is mapping - item.value.partitions | length == 0 # 新增排除loop设备的判断,直接对字符串类型的item.key做匹配 - not (item.key is search('loop'))
避坑提示
- 所有字符串匹配类过滤器(
search、match、regex_replace等),入参必须为字符串类型,传入字典、列表这类复杂类型时,一定会触发类型错误 - 用
dict2items转换字典后,返回的列表元素结构固定:每个元素是包含key(原字典键名,字符串类型)、value(原字典键值,即设备属性字典)的两级结构,不要把整个item丢给字符串过滤器做匹配 - 如果需要追加其他设备筛选规则(比如排除
sr0光盘设备、特定nvme设备),只需要在when条件中追加对应的not (item.key is search('匹配关键词'))判断即可,逻辑完全一致
内容的提问来源于stack exchange,提问作者AhmFM
相关产品推荐
相关产品推荐

