Ansible使用lineinfile循环导致主机顺序反转,有何解决办法?
问题:Ansible lineinfile循环添加服务器顺序反转
现有服务器状态文件包含多个标记区块,每个区块按顺序记录服务器状态。新服务器server4、server5、server6已按字母序加入Ansible内存清单,通过循环的lineinfile任务将新服务器添加到对应区块时,结果主机顺序反转;拆分为三个独立lineinfile任务则顺序正常,清单顺序已确认正确,求该问题的原因及解决办法。
原文件示例
#### START CUSTOM ANSIBLE BLOCK 5000 #### server1:5000 online server2:5000 online server3:5000 online #### END CUSTOM ANSIBLE BLOCK 5000 #### [...]<<< SOME OTHER TEXT HERE >>>[...] #### START CUSTOM ANSIBLE BLOCK 8000 #### server1:8000 online server2:8000 online server3:8000 online #### END CUSTOM ANSIBLE BLOCK 8000 #### [...]<<< MORE TEXT HERE >>>[...] #### START CUSTOM ANSIBLE BLOCK 12000 #### server1:12000 online server2:12000 online server3:12000 online #### END CUSTOM ANSIBLE BLOCK 12000 ####
循环任务代码
- name: Add the newly created servers to the status file in each section lineinfile: path: /opt/service/servers.lst line: "{{ item.line }}" insertbefore: "{{ item.insertbefore }}" loop: - line: '{{ inventory_hostname }}:5000 {{ detected_server_status }}' insertbefore: '#### END CUSTOM ANSIBLE BLOCK 5000 ####' - line: '{{ inventory_hostname }}:8000 {{ detected_server_status }}' insertbefore: '#### END CUSTOM ANSIBLE BLOCK 8000 ####' - line: '{{ inventory_hostname }}:12000 {{ detected_server_status }}' insertbefore: '#### END CUSTOM ANSIBLE BLOCK 12000 ####'
执行后反转结果示例
#### START CUSTOM ANSIBLE BLOCK 5000 #### server1:5000 online server2:5000 online server3:5000 online server6:5000 online server5:5000 online server4:5000 online #### END CUSTOM ANSIBLE BLOCK 5000 #### [...]<<< SOME OTHER TEXT HERE >>>[...] #### START CUSTOM ANSIBLE BLOCK 8000 #### server1:8000 online server2:8000 online server3:8000 online server6:8000 online server5:8000 online server4:8000 online #### END CUSTOM ANSIBLE BLOCK 8000 #### [...]<<< MORE TEXT HERE >>>[...] #### START CUSTOM ANSIBLE BLOCK 12000 #### server1:12000 online server2:12000 online server3:12000 online server6:12000 online server5:12000 online server4:12000 online #### END CUSTOM ANSIBLE BLOCK 12000 ####
原因分析
你的lineinfile循环任务是让新服务器按server4→server5→server6的顺序依次执行所有端口的插入操作,每次插入都使用insertbefore: '#### END CUSTOM ANSIBLE BLOCK XXXX ####',该参数会将新行插入到END标记的直接上方(即当前区块的最后一行位置):
server4先执行,将自己的三条记录分别插入到三个区块的现有行下方、END标记上方;server5接着执行,插入的行同样放在END标记上方,也就是server4记录的上方;server6最后执行,插入的行又放在server5记录的上方;
最终形成server6→server5→server4的倒序。
拆分成三个独立任务时顺序正常,大概率是因为拆分后每个端口区块的插入逻辑被间接调整,避免了后插入行覆盖前插入行的位置优先级。
解决办法
方案1:调整插入位置并使用正则去重
将insertbefore改为insertafter匹配区块起始行,同时添加regexp参数确保每行只插入一次,新行会按主机执行顺序依次添加到区块起始行的下方:
- name: Add newly created servers to 5000 section lineinfile: path: /opt/service/servers.lst line: "{{ inventory_hostname }}:5000 {{ detected_server_status }}" insertafter: '#### START CUSTOM ANSIBLE BLOCK 5000 ####' regexp: "{{ inventory_hostname }}:5000.*" - name: Add newly created servers to 8000 section lineinfile: path: /opt/service/servers.lst line: "{{ inventory_hostname }}:8000 {{ detected_server_status }}" insertafter: '#### START CUSTOM ANSIBLE BLOCK 8000 ####' regexp: "{{ inventory_hostname }}:8000.*" - name: Add newly created servers to 12000 section lineinfile: path: /opt/service/servers.lst line: "{{ inventory_hostname }}:12000 {{ detected_server_status }}" insertafter: '#### START CUSTOM ANSIBLE BLOCK 12000 ####' regexp: "{{ inventory_hostname }}:12000.*"
方案2:使用blockinfile批量生成区块内容
先收集所有服务器(原有+新服务器)的排序列表,再用blockinfile模块重新生成每个区块的内容,完全控制顺序:
- name: Get all servers in sorted order set_fact: all_servers: "{{ groups['existing_servers'] + groups['new_servers'] | sort }}" - name: Update 5000 section content blockinfile: path: /opt/service/servers.lst marker: "#### {mark} CUSTOM ANSIBLE BLOCK 5000 ####" content: | {% for server in all_servers %} {{ server }}:5000 online {% endfor %} - name: Update 8000 section content blockinfile: path: /opt/service/servers.lst marker: "#### {mark} CUSTOM ANSIBLE BLOCK 8000 ####" content: | {% for server in all_servers %} {{ server }}:8000 online {% endfor %} - name: Update 12000 section content blockinfile: path: /opt/service/servers.lst marker: "#### {mark} CUSTOM ANSIBLE BLOCK 12000 ####" content: | {% for server in all_servers %} {{ server }}:12000 online {% endfor %}
该方案不仅能保证顺序正确,还能统一维护区块内容,避免重复插入问题。
方案3:调整主机执行顺序(临时hack)
如果坚持使用原循环逻辑,可以让主机按倒序执行任务,这样后插入的行位置会符合预期,但该方式可靠性较低,不推荐:
- name: Add the newly created servers to the status file in each section lineinfile: path: /opt/service/servers.lst line: "{{ item.line }}" insertbefore: "{{ item.insertbefore }}" loop: - line: '{{ inventory_hostname }}:5000 {{ detected_server_status }}' insertbefore: '#### END CUSTOM ANSIBLE BLOCK 5000 ####' - line: '{{ inventory_hostname }}:8000 {{ detected_server_status }}' insertbefore: '#### END CUSTOM ANSIBLE BLOCK 8000 ####' - line: '{{ inventory_hostname }}:12000 {{ detected_server_status }}' insertbefore: '#### END CUSTOM ANSIBLE BLOCK 12000 ####' order: reverse
内容的提问来源于stack exchange,提问作者Tony
相关产品推荐
相关产品推荐

