Ansible 2.9.7跨play/主机访问变量问题求助
Ansible跨Play访问注册变量的正确方法
问题场景
使用Ansible 2.9.7版本,在同一playbook的两个play间传递变量时遇到问题:
- 第一play针对动态传入的主机(通过
-e "host=testhost"指定)执行任务,在本地创建临时目录并将结果注册为stagingdir变量,同一play内可正常访问该变量。 - 第二play针对
localhost执行任务,尝试通过hostvars访问第一play中注册的变量时,提示变量未定义。
原playbook代码:
- hosts: "{{host}}" gather_facts: false tasks: - name: Create local staging dir local_action: module: tempfile state: directory register: stagingdir - name: print stdout in same play debug: msg="Value of the variable is {{ hostvars[inventory_hostname].stagingdir.path }}" - hosts: localhost gather_facts: false tasks: - name: print stdout in next play debug: msg="Value of the variable is {{ hostvars[ "{{host}}" ].stagingdir.path }}"
执行报错:
# ansible-playbook test.yml -e "host=testhost" PLAY [testhost] ************************************************* TASK [Create local staging dir] ************************************************* changed: [testhost -> localhost] TASK [print stdout in same play] ************************************************ ok: [testhost] => { "msg": "Value of the variable is /tmp/ansible.IsLik6" } PLAY [localhost] **************************************************************** TASK [print stdout in next play] ************************************************ fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: \"hostvars['{{host}}']\" is undefined\n\nThe error appears to be in '/home/ooauto/ansible/test.yml': line 17, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: print stdout in next play\n ^ here\n"} PLAY RECAP ********************************************************************** testhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 localhost : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
错误原因
问题出在第二play的hostvars引用语法:hostvars[ "{{host}}" ]是错误写法。在Jinja2表达式({{ }}内部)中,不需要嵌套双大括号引用变量,直接使用变量名即可。嵌套的双大括号会被解析成字符串"{{host}}",而非host变量的实际值(此处为testhost),导致hostvars中找不到对应的主机条目,从而报错。
修正方案
方案1:修正hostvars引用语法
直接将第二play中的hostvars[ "{{host}}" ]改为hostvars[host],正确引用动态传入的主机名:
- hosts: "{{host}}" gather_facts: false tasks: - name: Create local staging dir local_action: module: tempfile state: directory register: stagingdir - name: print stdout in same play debug: msg="Value of the variable is {{ hostvars[inventory_hostname].stagingdir.path }}" - hosts: localhost gather_facts: false tasks: - name: print stdout in next play debug: msg="Value of the variable is {{ hostvars[host].stagingdir.path }}"
方案2:将变量存储到localhost的hostvars中
由于临时目录是在本地(localhost)创建的,更合理的方式是将注册的变量直接关联到localhost,后续访问更直观。在第一play中添加set_fact任务,将变量写入localhost的hostvars:
- hosts: "{{host}}" gather_facts: false tasks: - name: Create local staging dir local_action: module: tempfile state: directory register: stagingdir - name: print stdout in same play debug: msg="Value of the variable is {{ stagingdir.path }}" - name: Save staging dir path to localhost hostvars set_fact: staging_dir_path: "{{ stagingdir.path }}" delegate_to: localhost run_once: true - hosts: localhost gather_facts: false tasks: - name: print stdout in next play debug: msg="Value of the variable is {{ staging_dir_path }}"
验证结果
执行修正后的playbook,第二play将正常输出临时目录路径:
PLAY [localhost] **************************************************************** TASK [print stdout in next play] ************************************************ ok: [localhost] => { "msg": "Value of the variable is /tmp/ansible.IsLik6" }
内容的提问来源于stack exchange,提问作者hpzaramk
相关产品推荐
相关产品推荐

