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

Ansible剧本传递用户输入的库存组变量至后续Play报错求助

Ansible跨Play传递用户输入区域变量问题

问题场景

编写Ansible剧本时,想要实现:

  • 提示用户选择一个对应库存组的区域
  • 针对选中的库存组执行Play
  • 将该区域值设为fact,方便同剧本其他Play调用

库存文件内容

[ams]
device1
device2

[usa]
device1
device2

[jpn]
device1
device2

现有剧本内容

---
- name:  Play 1
  hosts: "{{ region }}"
  gather_facts: false
  connection: network_cli
  
  vars_prompt:
    - name: region
      prompt: "Region (ams, usa, jpn)"
      private: no

  tasks:
    - name: Make vars persistent
      set_fact:
        region: "{{ region }}"

    - name: check var
      debug:
        msg: "{{ region }}"


- name:  Play 2
  hosts: "{{ region }}"
  gather_facts: false
  connection: network_cli

  vars:
    region: "{{ hostvars['region'] }}"

  tasks:
    - name: debug
      debug: 
        msg: "{{ region }}"

遇到的错误

ERROR! The field 'hosts' has an invalid value, which includes an undefined variable. The error was: {{ hostvars['region'] }}: "hostvars['region']" is undefined. "hostvars['region']" is undefined. {{ hostvars['region'] }}: "hostvars['region']" is undefined. "hostvars['region']" is undefined

我试过用{{ hostvars['region']['region'] }},但还是报同样的错,是不是读取facts的方式有误?


问题原因

set_fact默认把变量绑定到目标主机上,而hostvars的正确用法是hostvars['主机名']['变量名'],你用hostvars['region']是把region当成了主机名,自然找不到。另外Play 2解析hosts字段时,还没确定要连接的主机,hostvars里也没有可用数据。

正确实现方式

方法1:全局定义vars_prompt(最简洁)

把vars_prompt移到剧本最外层,这样所有Play启动前就会获取用户输入,直接共享region变量:

---
vars_prompt:
  - name: region
    prompt: "Region (ams, usa, jpn)"
    private: no

- name:  Play 1
  hosts: "{{ region }}"
  gather_facts: false
  connection: network_cli

  tasks:
    - name: 检查变量
      debug:
        msg: "{{ region }}"


- name:  Play 2
  hosts: "{{ region }}"
  gather_facts: false
  connection: network_cli

  tasks:
    - name: 调试输出region变量
      debug: 
        msg: "{{ region }}"

方法2:将变量存到localhost的facts中

通过delegate_to: localhost把变量绑定到本地主机,后续Play从hostvars['localhost']读取:

---
- name:  Play 1
  hosts: "{{ region }}"
  gather_facts: false
  connection: network_cli
  
  vars_prompt:
    - name: region
      prompt: "Region (ams, usa, jpn)"
      private: no

  tasks:
    - name: 把region持久化到localhost
      set_fact:
        region: "{{ region }}"
      delegate_to: localhost
      run_once: true

    - name: 检查变量
      debug:
        msg: "{{ region }}"


- name:  Play 2
  hosts: "{{ hostvars['localhost']['region'] }}"
  gather_facts: false
  connection: network_cli

  tasks:
    - name: 调试输出region变量
      debug: 
        msg: "{{ hostvars['localhost']['region'] }}"

方法3:临时文件传递(适合复杂场景)

如果担心localhost不可用,可通过本地临时文件存储变量:

---
- name:  Play 1
  hosts: "{{ region }}"
  gather_facts: false
  connection: network_cli
  
  vars_prompt:
    - name: region
      prompt: "Region (ams, usa, jpn)"
      private: no

  tasks:
    - name: 将region写入临时文件
      copy:
        content: "{{ region }}"
        dest: "{{ playbook_dir }}/.region_tmp"
      delegate_to: localhost
      run_once: true

    - name: 检查变量
      debug:
        msg: "{{ region }}"


- name:  Play 2
  hosts: "{{ lookup('file', playbook_dir ~ '/.region_tmp') }}"
  gather_facts: false
  connection: network_cli

  tasks:
    - name: 调试输出region变量
      debug: 
        msg: "{{ lookup('file', playbook_dir ~ '/.region_tmp') }}"
    - name: 清理临时文件
      file:
        path: "{{ playbook_dir }}/.region_tmp"
        state: absent
      delegate_to: localhost
      run_once: true

内容的提问来源于stack exchange,提问作者hgalvan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 13:13:15