如何获取Ansible前序play的ansible_play_hosts_all?现有方案是否最优?
你的方案能跑,但不是最优解,存在冗余和小概率踩坑的点,有更简洁稳妥的写法。
现有方案的问题
你现在写的set_fact逻辑虽然能拿到目标主机列表,但有个容易踩的坑:run_once: true会随机挑一台第一play里的远程主机来触发任务,哪怕你加了delegate_to: localhost,Ansible还是得先连上这台被选中的远程主机才能启动任务执行,要是刚好选中的管理卡网不通、账号密码错了,这个存变量的任务直接就挂了,哪怕其他主机全是正常的。
推荐写法(零额外任务)
如果你的需求只是拿到被-l参数过滤后、第一个play初始选定的所有目标主机,完全不需要在第一个play里加任何存变量的任务,直接在第二个play的循环里用内置的inventory_hostnames查询就行:
- hosts: all gather_facts: false tasks: - name: 与管理卡做Redfish交互 uri: # 你的Redfish请求参数 register: redfish_result - hosts: localhost gather_facts: false tasks: - name: 生成巡检报告 template: src: report_template.j2 dest: ./output/redfish_report.md # 这里填的pattern和第一个play的hosts值保持一致即可,比如第一个play写的hosts: idrac_servers,这里就填'idrac_servers' loop: "{{ query('ansible.builtin.inventory_hostnames', 'all') }}"
这个写法的好处很明显:
- 不用加多余的任务,代码最干净
- 完全不依赖远程主机的连通性,不会因为单台机器故障导致拿不到主机列表
- 天然遵守
-l/--limit的过滤规则,返回的列表和第一个play的ansible_play_hosts_all完全一致
特殊场景优化写法
如果你需要拿到第一个play里实际执行成功的主机列表(自动排除中途连接失败、任务报错的主机),可以把存变量的任务改成纯本地执行,彻底避免远程主机连通性的影响:
- hosts: all gather_facts: false pre_tasks: - name: 存储当前play初始目标主机列表到本地 ansible.builtin.set_fact: target_hosts_all: "{{ ansible_play_hosts_all }}" delegate_to: localhost delegate_facts: true run_once: true connection: local ignore_unreachable: true tasks: - name: 与管理卡做Redfish交互 uri: # 你的Redfish请求参数 register: redfish_result post_tasks: - name: 存储成功执行完任务的主机列表到本地 ansible.builtin.set_fact: target_hosts_success: "{{ ansible_play_hosts }}" delegate_to: localhost delegate_facts: true run_once: true connection: local ignore_unreachable: true - hosts: localhost gather_facts: false tasks: - name: 生成巡检报告 template: src: report_template.j2 dest: ./output/redfish_report.md # 需要遍历初始目标主机用target_hosts_all,遍历成功执行的主机用target_hosts_success loop: "{{ target_hosts_success }}"
这里关键是给存变量的任务加了connection: local,任务直接在本地执行,根本不需要连任何远程主机,哪怕所有管理卡都连不上,存变量的操作也不会失败。
内容的提问来源于stack exchange,提问作者Fully Buzzword Compliant
相关产品推荐
相关产品推荐

