如何让Ansible循环强制处理列表中的重复项?
问题描述
我的vars文件内容如下:
images: - d2ac6a57-3669-44aa-a9f3-9690647ad1c5 - d2ac6a57-3669-44aa-a9f3-9690647ad1c5 ssh_users: - cirros - cirros flavors: - 1 - 2
我编写了如下Playbook,通过循环遍历变量将内容追加到配置文件:
- name: Append conf with images lineinfile: path: ./cloud/etc/conf line: "image = {{ item }}" loop: "{{ images }}" #... #省略ssh_users、flavors的类似任务
当前Ansible会跳过images和ssh_users中的第二个重复项,仅保留第一个条目:
实际输出
image = d2ac6a57-3669-44aa-a9f3-9690647ad1c5 flavor = 1 flavor = 2 ssh_user = cirros
但我需要保留所有列表条目(包括重复项),期望输出如下:
期望输出
image = d2ac6a57-3669-44aa-a9f3-9690647ad1c5 image = d2ac6a57-3669-44aa-a9f3-9690647ad1c5 flavor = 1 flavor = 2 ssh_user = cirros ssh_user = cirros
如何强制Ansible输出列表中的每一个条目?
解决方案
问题根源是lineinfile模块的默认行为:它会检查目标文件中是否已存在相同行,若存在则跳过写入,这直接导致重复条目被忽略。以下是两种可行的解决方法:
方法1:修改lineinfile参数,规避重复行检测
为lineinfile任务添加insertafter: EOF,同时设置一个永远不会匹配现有内容的regexp规则,让模块认为每一行都是全新内容,从而不跳过重复项。
示例任务代码:
- name: Append conf with images lineinfile: path: ./cloud/etc/conf line: "image = {{ item }}" insertafter: EOF regexp: '^image = {{ item }}_NO_MATCH_' # 不可能匹配的规则 loop: "{{ images }}" - name: Append conf with ssh users lineinfile: path: ./cloud/etc/conf line: "ssh_user = {{ item }}" insertafter: EOF regexp: '^ssh_user = {{ item }}_NO_MATCH_' loop: "{{ ssh_users }}" - name: Append conf with flavors lineinfile: path: ./cloud/etc/conf line: "flavor = {{ item }}" insertafter: EOF regexp: '^flavor = {{ item }}_NO_MATCH_' loop: "{{ flavors }}"
方法2:使用copy模块结合Jinja2模板(更简洁)
如果配置内容较多,推荐用模板生成完整配置文件,再通过copy模块部署,这种方式能直接确保所有条目(包括重复项)都被写入。
- 创建Jinja2模板文件
conf.j2:
{% for img in images %} image = {{ img }} {% endfor %} {% for user in ssh_users %} ssh_user = {{ user }} {% endfor %} {% for flavor in flavors %} flavor = {{ flavor }} {% endfor %}
- 在Playbook中调用模板:
- name: Generate conf file from template copy: src: conf.j2 dest: ./cloud/etc/conf mode: '0644'
内容的提问来源于stack exchange,提问作者e god
相关产品推荐
相关产品推荐

