Ansible Playbook求助:向/etc/hosts添加主机条目格式错误
解决Ansible批量更新/etc/hosts文件的分行问题
问题场景
我的Inventory文件内容如下:
# PostgreSQL nodes [all] 192.168.63.31 hostname=pgnode1 192.168.63.32 hostname=pgnode2 192.168.63.33 hostname=pgnode3
需要将所有节点的IP和主机名按以下格式添加到每个节点的/etc/hosts文件中:
192.168.63.31 pgnode1 192.168.63.32 pgnode2 192.168.63.33 pgnode3
之前尝试用lineinfile模块直接循环生成内容,结果所有内容挤在一行;用blockinfile模块也没实现分行,得到的是一行拼接的内容:
192.168.63.32 pgnode2 192.168.63.33 pgnode3 192.168.63.31 pgnode1
正确实现方法
方法1:遍历每个主机单独添加条目
用loop循环遍历groups.all中的每个主机,为每个主机单独生成一行/etc/hosts条目,确保每行独立:
- name: 批量更新/etc/hosts文件 hosts: all become: yes tasks: - name: 为每个PostgreSQL节点添加hosts条目 lineinfile: path: /etc/hosts state: present line: "{{ item }} {{ hostvars[item]['hostname'] }}" loop: "{{ groups.all }}"
方法2:以块形式添加多行内容
如果想把这些条目作为一个整体块添加(带标记方便后续维护),可以用blockinfile配合Jinja2的循环和换行保留语法:
- name: 以块形式更新/etc/hosts文件 hosts: all become: yes tasks: - name: 添加PostgreSQL节点hosts块 blockinfile: path: /etc/hosts state: present marker: "# {mark} PostgreSQL Nodes Hosts" block: | {% for host in groups.all %} {{ host }} {{ hostvars[host]['hostname'] }} {% endfor %}
也可以用join过滤器简化写法,把循环结果用换行符拼接:
block: "{{ groups.all | map('regex_replace', '^(.*)$', '\\1 ' ~ hostvars[\\1]['hostname']) | join('\n') }}"
失败原因说明
- 直接在
lineinfile的line参数里写循环,Ansible会把循环输出的所有内容合并成单行文本插入,不会自动换行 - 用
blockinfile时如果没使用|来保留换行格式,Jinja2循环生成的内容会被自动拼接成一行
内容的提问来源于stack exchange,提问作者Majid Chaudhary
相关产品推荐
相关产品推荐

