You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 16:50:22