Ansible 2.4.2.0跨Play访问变量失败排查求助
Ansible跨Play访问注册变量的问题解决办法
嘿,我来帮你搞定这个Ansible跨Play访问变量的问题!你用Ansible 2.4.2.0写的Playbook里,第一个Play在all-compute-host主机上用heat-admin执行hostname命令并注册了变量,第二个Play想在localhost通过hostvars访问这个变量,但一直报变量未定义的错误,试过好几种写法都不行对吧?
先看看你原来的Playbook代码:
$ cat test.yml - name: Finding Master VMs hosts: all-compute-host remote_user: heat-admin tasks: - name: Getting master VM's hostname shell: hostname register: hostname_output - name: Access in different play hosts: localhost connection: local tasks: - name: Testing vars debug: var='{{ hostvars[item]['hostname_output']['stdout'] }}' with_items: groups['all-compute-host']
报错信息是这样的:
TASK [Testing vars] ******************************************************************************************************************* fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: u\"hostvars['groups['all-compute-host']']\" is undefined\n\nThe error appears to have been in '/tmp/test.yml': line 18, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n tasks:\n - name: Testing vars\n ^ here\n\nexception type: <class 'ansible.errors.AnsibleUndefinedVariable'>\nexception: u\"hostvars['groups['all-compute-host']']\" is undefined"} to retry, use: --limit @/tmp/test.retry
问题出在哪?
仔细看报错信息里的hostvars['groups['all-compute-host']'],这说明Ansible把groups['all-compute-host']当成了一个字符串键,而不是去引用组变量,根本原因有两个:
with_items里的groups['all-compute-host']没有用{{ }}包裹,Ansible不会把它当成变量解析,而是直接作为字符串处理,导致循环时item的值就是groups['all-compute-host'],自然hostvars里没有这个主机。debug的var参数不需要用{{ }}包裹变量,加了之后反而会引发引号嵌套的解析问题。
正确的解决方案
把第二个Play里的debug任务改成下面这样:
- name: Access in different play hosts: localhost connection: local tasks: - name: Testing vars debug: var: hostvars[item].hostname_output.stdout with_items: "{{ groups['all-compute-host'] }}"
或者用方括号的写法也可以,效果一样:
debug: var: hostvars[item]['hostname_output']['stdout']
为什么之前的写法都不行?
我来给你逐个分析:
debug: var=hostvars[item]['hostname_output']['stdout']:with_items没加{{ }},item还是字符串,无法正确匹配主机。debug: var=hostvars.item.hostname_output.stdout:动态变量名不能用点语法,得用hostvars[item]这种方括号形式才能解析item变量。debug: var=hostvars.all-compute-host.hostname_output.stdout:hostvars的键是单个主机的inventory名称,不是组名,直接用组名访问肯定找不到。debug: var=hostvars['all-compute-host']['hostname_output']['stdout']:同上,组名不能作为hostvars的键,得遍历组里的每个主机。debug: var='hostvars.compute01.hostname_output.stdout':如果compute01是组里的单个主机,这个写法是对的,但只能访问这一台,没法遍历整个组。
修正后的完整Playbook
- name: Finding Master VMs hosts: all-compute-host remote_user: heat-admin tasks: - name: Getting master VM's hostname shell: hostname register: hostname_output - name: Access in different play hosts: localhost connection: local tasks: - name: Testing vars debug: var: hostvars[item].hostname_output.stdout with_items: "{{ groups['all-compute-host'] }}"
这样修改后,Ansible会正确遍历all-compute-host组里的每台主机,然后通过hostvars[item]获取对应主机上注册的hostname_output变量,就能正常输出每台主机的 hostname 了。
内容的提问来源于stack exchange,提问作者veerendra2
相关产品推荐
相关产品推荐

