如何在任意主机存在openvz事实时让所有主机执行Ansible任务
你原有代码的问题是循环执行set_fact时没有做列表追加,每次执行都会直接覆盖virt_list的值,且没有加run_once限制导致每个受管主机都单独执行了一次收集,最终每个主机只能拿到自己对应的条目,无法完成全量列表的汇总。
最简实现方案(无需额外收集列表)
直接在目标任务的when条件中用Jinja2表达式做判断,无需单独设置fact,一行即可实现需求:
- name: 存在OpenVZ主机时所有节点执行的指定任务 # 此处替换为你实际要执行的任务动作 yum: name: fuse state: present when: groups['all'] | map('extract', hostvars, 'ansible_virtualization_type') | select('equalto', 'openvz') | list | length > 0
表达式逻辑说明:
- 先提取全量主机组中所有节点的
ansible_virtualization_type属性 - 筛选出值为
openvz的结果 - 转换为列表后判断长度,大于0则说明存在符合条件的主机
如果你确实需要保留OpenVZ主机列表供后续多任务复用
可以用以下修正后的写法收集列表:
- name: 收集所有OpenVZ虚拟化的主机列表 set_fact: virt_list: "{{ virt_list | default([]) + [{'host': item, 'type': 'openvz'}] }}" when: hostvars[item].ansible_virtualization_type == "openvz" with_items: "{{ groups['all'] }}" run_once: true delegate_to: localhost delegate_facts: true
新增的两个关键配置作用:
run_once: true:让收集任务仅在第一个主机上执行一次,避免所有受管节点重复执行virt_list | default([]) + [xxx]:初始化空列表并做元素追加,不会每次循环覆盖原有值
后续其他任务可以直接用以下条件判断:
when: hostvars['localhost'].virt_list | default([]) | length > 0
内容的提问来源于stack exchange,提问作者Aleritty
相关产品推荐
相关产品推荐

