为什么 blockinfile 模块只向文件添加一行?

Why does the blockinfile module only add one line to the file?

我正在尝试使用 ansible 的 blockinfile 模块将块文本写入文件。

测试目的/tmp/hosts,这里是blockinfile-test.yaml

的内容
---
- hosts: web
  gather_facts: false
  tasks:
  - name: Add mappings to /tmp/hosts
    blockinfile:
      path: /tmp/hosts
      create: yes
      block: |
        {{ item.ip }} {{ item.name }}
    loop:
      - { name: host1, ip: 10.180.104.100 }
      - { name: host2, ip: 10.180.104.101 }

这是库存文件

[myself]
ansible-main.local

[web]
10.180.104.101

然后运行命令应用

ansible-playbook -i hosts  blockinfile-test.yaml

TASK [Add mappings to /tmp/hosts] *****************************
changed: [10.180.104.101] => (item={'name': 'host1', 'ip': '10.180.104.100'})
changed: [10.180.104.101] => (item={'name': 'host2', 'ip': '10.180.104.101'})

PLAY RECAP ********************
10.180.104.101 : ok=1  changed=1 unreachable=0 failed=0 skipped=0 rescued=0  ignored=0

然后,我检查了努力,但在文件中只附加了一行 /tmp/hosts

# BEGIN ANSIBLE MANAGED BLOCK
10.180.104.101 host2
# END ANSIBLE MANAGED BLOCK

为什么只有一行写入文件?

是否缺少要阻止文件的内容?

创建唯一的 marker 个块。否则,块将相互覆盖,例如

  - name: Add mappings to /tmp/hosts
    blockinfile:
      marker: "# {mark} ANSIBLE MANAGED BLOCK {{ item.name }}"
      path: /tmp/hosts
      create: true
      block: |
        {{ item.ip }} {{ item.name }}
    loop: "{{ data }}"
    vars:
      data:
        - {name: host1, ip: 10.180.104.100}
        - {name: host2, ip: 10.180.104.101}

将创建文件

shell> cat /tmp/hosts 
# BEGIN ANSIBLE MANAGED BLOCK host1
10.180.104.100 host1
# END ANSIBLE MANAGED BLOCK host1
# BEGIN ANSIBLE MANAGED BLOCK host2
10.180.104.101 host2
# END ANSIBLE MANAGED BLOCK host2

下一个选项是迭代块中的列表,例如

  - name: Add mappings to /tmp/hosts
    blockinfile:
      marker: "# {mark} ANSIBLE MANAGED BLOCK data"
      path: /tmp/hosts
      create: true
      block: |
        {% for item in data %}
        {{ item.ip }} {{ item.name }}
        {% endfor %}
    vars:
      data:
        - {name: host1, ip: 10.180.104.100}
        - {name: host2, ip: 10.180.104.101}

将创建具有单个块的文件。这将使文件更易于阅读

shell> cat /tmp/hosts 
# BEGIN ANSIBLE MANAGED BLOCK data
10.180.104.100 host1
10.180.104.101 host2
# END ANSIBLE MANAGED BLOCK data

缺点是如果有任何变化,您将不得不更新整个块。在第一种情况下,您将能够更新单个主机。


您可以使用lineinfile来更新方块,例如

  - name: Update mappings in /tmp/hosts
    lineinfile:
      path: /tmp/hosts
      create: true
      regexp: '^\s*(.*?)\s+{{ item.name }}\s*$'
      line: "{{ item.ip }} {{ item.name }}"
    loop: "{{ data }}"
    vars:
      data:
        - {name: host1, ip: 10.180.104.100}
        - {name: host2, ip: 10.180.104.101}

是幂等的

TASK [Update mappings in /tmp/hosts] ******************************
ok: [localhost] => (item={'name': 'host1', 'ip': '10.180.104.100'})
ok: [localhost] => (item={'name': 'host2', 'ip': '10.180.104.101'})

备注

  • 请参阅hosts.yml了解如何验证数据和从模板创建文件

  • 参见示例 template

  • 以及此模板的 data 示例。