Ansible使用insertafter在匹配行后插入新行失败问题排查
Ansible lineinfile 插入XML行失败问题解决
问题场景
在RHEL 7.9服务器上使用Ansible 2.9,需要在firewalld zone配置文件/etc/firewalld/zones/admin.xml中,仅当<source address="192.168.7.0/24"/>行存在时,在该行后插入<source address="192.168.16.0/24"/>。当前执行剧本后,新行始终被追加到文件末尾,常规字符串匹配无效。
原测试剧本
--- - name: update firewalld hosts: rhel-08-dev gather_facts: false become: true tasks: - name: Add IP x.x.x.x to admin.xml lineinfile: backup: yes path: /etc/firewalld/zones/admin.xml insertafter: '<source address="192.168.7.0/24"/>' firstmatch: yes state: present line: '<source address="192.168.16.0/24"/>'
文件修改前状态
[zone] <source address="192.168.4.0/24"/> <source address="192.168.5.0/24"/> <source address="192.168.6.0/24"/> <source address="192.168.7.0/24"/> <source address="192.168.18.0/24"/> <source address="192.168.23.0/24"/> [zone]
期望修改后状态
[zone] <source address="192.168.4.0/24"/> <source address="192.168.5.0/24"/> <source address="192.168.6.0/24"/> <source address="192.168.7.0/24"/> <source address="192.168.16.0/24"/> <!-- 需插入此处 --> <source address="192.168.18.0/24"/> <source address="192.168.23.0/24"/> [zone]
解决方案
问题根源在于原剧本中insertafter的字符串匹配未考虑XML行的缩进、空白字符,导致无法精准匹配目标行。改用正则表达式匹配目标行,忽略行首行尾空白即可解决。
修正后的剧本
--- - name: update firewalld hosts: rhel-08-dev gather_facts: false become: true tasks: - name: Add IP 192.168.16.0/24 to admin.xml lineinfile: backup: yes path: /etc/firewalld/zones/admin.xml # 正则匹配目标行,忽略行首行尾空白 insertafter: '^\s*<source address="192.168.7.0/24"/>\s*$' firstmatch: yes state: present line: '<source address="192.168.16.0/24"/>'
关键说明
- 正则匹配:
^\s*匹配行首任意数量的空白字符(空格、制表符),\s*$匹配行尾任意数量的空白字符,确保能匹配带有缩进的目标行。 - 取消HTML转义:原剧本中使用的
<、"是HTML转义字符,在Ansible YAML剧本中直接使用<、"即可,无需转义。 - firstmatch: yes:确保只在第一个匹配的目标行后插入新行,避免重复插入。
执行修正后的剧本,即可将新行插入到指定位置。
内容的提问来源于stack exchange,提问作者mushibugyo
相关产品推荐
相关产品推荐

