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

解决Ansible遍历清单组主机执行文件更新任务的循环问题

问题:Ansible多主机组遍历执行文件更新任务失败

现有配置

Playbook代码

---
- hosts: dev   
  gather_facts: yes
  become: true   
  become_method: su   
  become_user: xxxxx

  tasks:
  - name: Update the file contents
    replace:
      path: "/path/to/file{{ item.path  }}.xml"
      regexp: '(xxxxxxx[\s\S]*yyyyyyy$)'
      replace: "/zzz/zzzz/{{ item.replace }}.dat /qqqq/qqqqq/q"
      backup: yes
    with_items:
      - { path: "{{ groups['dev'] }}", replace: "{{ groups['pc'] }}" }

Inventory配置

[dev] 
host1 
host2

[pc] 
1234 
6789

执行报错

failed: [host1] (item={u'path': [u'host1', u'host2'], u'replace': [u'1234', u'6789']}) => {"ansible_loop_var": "item", "changed": false, "
item": {"path": ["host1", "host2"], "replace": ["1234", "6789"]}, "msg": "Path /path/to/file[u'host1', u'host2'].xml does not exist !", "rc": 257}

failed: [host2] (item={u'path': [u'host1', u'host2'], u'replace': [u'1234', u'6789']}) => {"ansible_loop_var": "item", "changed": false, "
item": {"path": ["host1", "host2"], "replace": ["1234", "6789"]}, "msg": "Path /path/to/file[u'host1', u'host2'].xml does not exist !", rc": 257}

期望效果

[host1] (item={u'path': [u'host1'], u'replace': [u'1234']}) "msg": "Path /path/to/file/host1.xml 
[host2] (item={u'path': [u'host2'], u'replace': [u'6789']}) "msg": "Path /path/to/file/host2.xml 

问题原因

groups['dev']和groups['pc']会返回整个组的列表,而非当前主机对应的单个值。当dev组存在多台主机时,item.path被赋值为整个dev主机列表,导致文件路径拼接错误,无法找到目标文件。

解决方案

方案1:利用主机索引匹配对应值

通过当前主机在dev组中的索引,获取pc组对应位置的值,实现一一匹配:

---
- hosts: dev   
  gather_facts: yes
  become: true   
  become_method: su   
  become_user: xxxxx

  tasks:
  - name: Update the file contents
    replace:
      path: "/path/to/file{{ inventory_hostname }}.xml"
      regexp: '(xxxxxxx[\s\S]*yyyyyyy$)'
      replace: "/zzz/zzzz/{{ groups['pc'][groups['dev'].index(inventory_hostname)] }}.dat /qqqq/qqqqq/q"
      backup: yes
  • 说明:
    • inventory_hostname直接调用当前执行任务的主机名,无需遍历组列表
    • groups['dev'].index(inventory_hostname)获取当前主机在dev组的位置索引
    • 用该索引从pc组中取出对应值,完成dev主机与pc值的一一对应

方案2:预定义主机-替换值映射列表

直接在Playbook中明确每个主机对应的替换值,通过条件判断执行任务:

---
- hosts: dev   
  gather_facts: yes
  become: true   
  become_method: su   
  become_user: xxxxx

  vars:
    host_replace_map:
      - { host: "host1", replace_val: "1234" }
      - { host: "host2", replace_val: "6789" }

  tasks:
  - name: Update the file contents
    replace:
      path: "/path/to/file{{ item.host }}.xml"
      regexp: '(xxxxxxx[\s\S]*yyyyyyy$)'
      replace: "/zzz/zzzz/{{ item.replace_val }}.dat /qqqq/qqqqq/q"
      backup: yes
    when: inventory_hostname == item.host
    loop: "{{ host_replace_map }}"
  • 说明:
    • 定义host_replace_map清晰展示主机与替换值的对应关系
    • 通过when条件仅在当前主机匹配时执行任务,避免无效遍历

方案3:使用Inventory主机变量(推荐)

修改Inventory,直接给dev组主机添加专属变量,实现最简洁的配置:
修改后的Inventory:

[dev] 
host1 replace_val=1234
host2 replace_val=6789

[pc] 
1234 
6789

简化后的Playbook:

---
- hosts: dev   
  gather_facts: yes
  become: true   
  become_method: su   
  become_user: xxxxx

  tasks:
  - name: Update the file contents
    replace:
      path: "/path/to/file{{ inventory_hostname }}.xml"
      regexp: '(xxxxxxx[\s\S]*yyyyyyy$)'
      replace: "/zzz/zzzz/{{ replace_val }}.dat /qqqq/qqqqq/q"
      backup: yes
  • 说明:
    • 每个dev主机直接携带自身的replace_val变量,无需处理组索引或额外列表
    • 代码最简洁,维护成本最低,是最优解决方案

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 06:05:37