Ansible中基于主机名调用对应变量实现文件正则替换的错误排查与解决方案
Ansible 动态变量引用错误的解决方法
我来帮你分析下问题出在哪,以及怎么解决:
你的错误点
你遇到的问题主要有两个:
- 双大括号语法错误:在Ansible的Jinja2模板里,变量只需要用一层
{{ }}包裹就行,你写的{{ {{ansible_hostname}}.location }}属于嵌套大括号的语法错误,Ansible完全没法解析这种写法。 - 动态变量引用逻辑错了:要是直接写
{{ ansible_hostname.location }},Ansible会误以为你要找一个叫ansible_hostname的变量的location属性,而不是把ansible_hostname的实际值(比如"VELABx")当作变量名,去调用你定义好的VELABx变量。
正确的解决方式
要动态匹配和当前ansible_hostname对应的变量,有两种常用的靠谱方法:
方法1:用vars字典直接访问
Ansible会把所有你定义的变量都存到vars字典里,你可以通过变量名的字符串来获取对应变量。比如vars[ansible_hostname]就能拿到当前主机对应的VELABx或VELABy变量,接着再取它的location属性就行:
- name: Replace location with matching variable value replace: dest: "/path/to/file" regexp: 'location' replace: "{{ vars[ansible_hostname].location }}" remote_user: rssuser become: no
这种写法不需要写两个带when条件的任务,不管当前主机是VELABx还是VELABy,都能自动匹配对应的变量值,后期新增主机变量也不用改任务代码,很方便。
方法2:使用lookup('vars')插件
另一种方式是用Ansible的lookup插件来动态获取变量,效果和上面一样:
- name: Replace location with matching variable value replace: dest: "/path/to/file" regexp: 'location' replace: "{{ lookup('vars', ansible_hostname).location }}" remote_user: rssuser become: no
如果你偏好分任务写法(可选)
要是你就想保留按主机名分任务的方式,那只需要修正变量引用的写法就行,不用嵌套大括号:
- name: Replace location for VELABx replace: dest: "/path/to/file" regexp: 'location' replace: "{{ VELABx.location }}" remote_user: rssuser become: no when: ansible_hostname == "VELABx" - name: Replace location for VELABy replace: dest: "/path/to/file" regexp: 'location' replace: "{{ VELABy.location }}" remote_user: rssuser become: no when: ansible_hostname == "VELABy"
不过这种写法扩展性差,新增主机就得加新任务,还是动态引用的方式更推荐。
内容的提问来源于stack exchange,提问作者Mr. Green
相关产品推荐
相关产品推荐

