使用Ansible replace模块修改resolved.conf无实际变更问题求助
问题
使用Ansible的replace模块修改/etc/systemd/resolved.conf时,任务日志显示成功完成1处替换,但实际查看文件发现#DNS=行并未被修改为指定的DNS条目。相关配置、日志及文件现状如下:
配置代码
vars.yml:
dns_server: "192.168.22.12 192.168.22.13" #dns_server: "192.168.22.12,192.168.22.13"
Ansible任务:
- name: Handle user DNS entry for /etc/systemd/resolved.conf ansible.builtin.set_fact: DNS_ENTRY: "{{ dns_server is defined | regex_replace(',', ' ') }}" when: - dns_server is defined and dns_server is defined | regex_search(',') - name: Use original user entry if no comma found ansible.builtin.set_fact: DNS_ENTRY: "{{ dns_server }}" when: - dns_server is defined and not dns_server| regex_search(',') - name: Ensure DNS configuration is set in resolved.conf ansible.builtin.replace: path: /etc/systemd/resolved.conf regexp: '^#DNS=' replace: 'DNS={{ DNS_ENTRY }}'
任务执行日志
TASK [Handle user DNS entry for /etc/systemd/resolved.conf] ******************** task path: /opt/vi/firstboot/ansible/tasks/10-network.yml:33 skipping: [127.0.0.1] => { "changed": false, "skip_reason": "Conditional result was False" } TASK [Use original user entry if no comma found] ******************************* task path: /opt/vi/firstboot/ansible/tasks/10-network.yml:39 ok: [127.0.0.1] => { "ansible_facts": { "DNS_ENTRY": "192.168.22.12 192.168.22.13" }, "changed": false } TASK [Ensure DNS configuration is set in resolved.conf] ************************ task path: /opt/vi/firstboot/ansible/tasks/10-network.yml:45 <127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: root <127.0.0.1> EXEC /bin/sh -c 'echo ~root && sleep 0' <127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp `"&& mkdir "` echo /root/.ansible/tmp/ansible-tmp-1709713866.0024374-2195-81793838038995 `" && echo ansible-tmp-1709713866.0024374-2195-81793838038995="` echo /root/.ansible/tmp/ansible-tmp-1709713866.0024374-2195-81793838038995 `" ) && sleep 0' Using module file /usr/lib/python3/dist-packages/ansible/modules/replace.py <127.0.0.1> PUT /root/.ansible/tmp/ansible-local-1398ho9ozv7y/tmpfbiy0ps4 TO /root/.ansible/tmp/ansible-tmp-1709713866.0024374-2195-81793838038995/AnsiballZ_replace.py <127.0.0.1> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1709713866.0024374-2195-81793838038995/ /root/.ansible/tmp/ansible-tmp-1709713866.0024374-2195-81793838038995/AnsiballZ_replace.py && sleep 0' <127.0.0.1> EXEC /bin/sh -c '/usr/bin/python3 /root/.ansible/tmp/ansible-tmp-1709713866.0024374-2195-81793838038995/AnsiballZ_replace.py && sleep 0' <127.0.0.1> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1709713866.0024374-2195-81793838038995/ > /dev/null 2>&1 && sleep 0' changed: [127.0.0.1] => { "changed": true, "invocation": { "module_args": { "after": null, "attributes": null, "backup": false, "before": null, "encoding": "utf-8", "group": null, "mode": null, "owner": null, "path": "/etc/systemd/resolved.conf", "regexp": "^#DNS=", "replace": "DNS=192.168.22.12 192.168.22.13", "selevel": null, "serole": null, "setype": null, "seuser": null, "unsafe_writes": false, "validate": null } }, "msg": "1 replacements made" }
实际文件内容
cat /etc/systemd/resolved.conf # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation; either version 2.1 of the License, or (at your option) # any later version. # # Entries in this file show the compile time defaults. Local configuration # should be created by either modifying this file, or by creating \"drop-ins\" in # the resolved.conf.d/ subdirectory. The latter is generally recommended. # Defaults can be restored by simply deleting this file and all drop-ins. # # Use 'systemd-analyze cat-config systemd/resolved.conf' to display the full config. # # See resolved.conf(5) for details. [Resolve] # Some examples of DNS servers which may be used for DNS= and FallbackDNS=: # Cloudflare: 1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com 2606:4700:4700::1111#cloudflare-dns.com 2606:4700:4700::1001#cloudflare-dns.com # Google: 8.8.8.8#dns.google 8.8.4.4#dns.google 2001:4860:4860::8888#dns.google 2001:4860:4860::8844#dns.google # Quad9: 9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net 2620:fe::fe#dns.quad9.net 2620:fe::9#dns.quad9.net #DNS= #FallbackDNS= #Domains= #DNSSEC=no #DNSOverTLS=no #MulticastDNS=no #LLMNR=no #Cache=no-negative #CacheFromLocalhost=no #DNSStubListener=yes #DNSStubListenerExtra= #ReadEtcHosts=yes #ResolveUnicastSingleLabel=no
排查与解决
1. 正则表达式匹配范围不足
你的regexp: '^#DNS='使用了^(行首锚定),但如果目标#DNS=行前存在空格或制表符(可能肉眼难以察觉),这个正则就无法匹配到目标行。而Ansible日志显示的1处替换,大概率是匹配到了文件中其他符合^#DNS=规则的行(比如注释里的某行)。
解决方法:修改正则表达式,允许行首有任意空白字符:
regexp: '^\s*#DNS='
\s*表示匹配0个或多个空白字符(空格、制表符),这样无论目标行是否缩进,都能准确匹配。
2. 修复set_fact任务的条件错误
第一个set_fact任务的条件存在语法错误:dns_server is defined | regex_search(',')是对布尔值dns_server is defined执行正则匹配,这显然不符合预期,应该直接对dns_server做正则检查。修改后的任务:
- name: Handle user DNS entry for /etc/systemd/resolved.conf ansible.builtin.set_fact: DNS_ENTRY: "{{ dns_server | regex_replace(',', ' ') }}" when: - dns_server is defined - dns_server | regex_search(',')
3. 验证匹配目标行
在执行replace任务前,先添加一个shell任务确认目标行的格式:
- name: Check target DNS line format ansible.builtin.shell: grep -n "\s*#DNS=" /etc/systemd/resolved.conf register: dns_line - name: Print DNS line details ansible.builtin.debug: var: dns_line.stdout
这能帮你确认目标行是否有缩进,以及具体位置。
4. 启用备份验证替换结果
给replace模块添加backup: yes参数,执行后会在原文件目录生成带时间戳的备份文件,对比备份文件和修改后的文件,就能清楚看到替换的具体内容:
- name: Ensure DNS configuration is set in resolved.conf ansible.builtin.replace: path: /etc/systemd/resolved.conf regexp: '^\s*#DNS=' replace: 'DNS={{ DNS_ENTRY }}' backup: yes
内容的提问来源于stack exchange,提问作者cz75ww
相关产品推荐
相关产品推荐

