You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何借助ansible_play_hosts为各主机生成匹配与非匹配项列表?

Ansible 跨主机生成匹配/非匹配项列表解决方案

场景说明

各主机的found_items列表如下:

  • host-1:
- /tmp/a
- /tmp/b
- /tmp/c
- /tmp/d
- /tmp/e
  • host-2:
- /tmp/b
- /tmp/c
  • host-3:
- /tmp/c
- /tmp/d

技术需求

必须使用魔术变量ansible_play_hosts,为play中的每个主机动态生成两个列表:

  • 匹配项列表:当前主机found_items中,在至少一个其他主机的found_items里存在的项(例如host-1的匹配项为/tmp/b、/tmp/c、/tmp/d)
  • 非匹配项列表:当前主机found_items中,仅在自身存在的项(例如host-1的非匹配项为/tmp/a、/tmp/e)

已尝试代码

- name: set fact for shared files
  set_fact:
    shared_files: "{{ hostvars[item].found_items }}"
  loop: "{{ ansible_play_hosts }}"
  when:
    - hostvars[item.ansible_host].found_items is defined
    - hostvars[item.ansible_host].found_items == found_items

注:变量found_items存储各主机对应的列表。

问题分析

原有代码存在两个核心问题:

  1. 条件判断逻辑错误:hostvars[item.ansible_host].found_items == found_items是在寻找和当前主机found_items完全一致的主机,不符合“项在其他主机存在”的需求;
  2. 主机变量访问错误:item是ansible_play_hosts返回的主机名,直接用hostvars[item]访问即可,无需item.ansible_host。

解决方案

以下代码通过ansible_play_hosts实现需求:

- name: 收集所有主机的found_items列表
  set_fact:
    all_hosts_found: "{{ ansible_play_hosts | map('extract', hostvars, 'found_items') | list }}"
  run_once: true

- name: 生成匹配项与非匹配项列表
  set_fact:
    # 匹配项:当前主机项在其他主机中出现过
    matched_items: >-
      {{ found_items | select('in', all_hosts_found | flatten | difference(found_items)) | list }}
    # 非匹配项:当前主机项仅在自身存在
    unmatched_items: >-
      {{ found_items | reject('in', all_hosts_found | flatten | difference(found_items)) | list }}

逻辑说明

  1. all_hosts_found:通过ansible_play_hosts遍历所有主机,提取每个主机的found_items,组成包含所有主机列表的二维数组;
  2. all_hosts_found | flatten | difference(found_items):将二维数组转为一维,再剔除当前主机的所有项,得到其他所有主机的所有项的合集;
  3. matched_items:筛选当前主机found_items中存在于上述合集的项,即跨主机存在的匹配项;
  4. unmatched_items:筛选当前主机found_items中不存在于上述合集的项,即仅自身存在的非匹配项。

内容的提问来源于stack exchange,提问作者Kevin C

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 10:26:01