Ansible首个主机为变量时,如何在Play间传递Fact?
Ansible跨Play访问动态主机Fact的问题解决
问题场景
我写了个包含两个Play的Ansible剧本:
- 第一个Play:负责数据采集、创建自定义Fact
my_fact,同时生成动态inventory - 第二个Play:调用第一个Play生成的动态inventory,但访问
my_fact时总是失败
我知道Fact是和对应Play的主机关联的,一般用hostvars就能跨Play访问,但第一个Play的hosts是通过额外变量传进来的,不知道这种场景下该怎么正确用hostvars。下面给你讲两种可行的解决办法,以及各自的适用场景。
方法一:用hostvars精准访问目标主机的Fact
核心是先明确第一个Play里的目标主机标识,再通过hostvars定位到对应的Fact。
第一步:确保第一个Play的Fact绑定正确
先确认第一个Play里设置Fact的任务是针对传入的目标主机执行的,比如:
- name: 第一个Play:采集数据+设置Fact+生成动态inventory hosts: "{{ target_hosts }}" # target_hosts是通过-e传入的额外变量 tasks: - name: 采集数据并创建自定义Fact set_fact: my_fact: "这里是采集到的具体数据" # 如果数据是在本地生成的,需要加delegate_to: localhost,根据实际情况调整
第二步:第二个Play中通过hostvars访问
如果target_hosts是一个主机组,直接遍历组内主机来访问:
- name: 第二个Play:使用动态inventory并访问Fact hosts: dynamic_inv_group # 第一个Play生成的动态inventory组名 tasks: - name: 获取第一个Play设置的my_fact debug: msg: "主机{{ item }}的Fact值:{{ hostvars[item].my_fact }}" loop: "{{ groups[target_hosts] }}" delegate_to: localhost # 不需要在动态inventory主机上执行的话加这个
如果target_hosts是单个主机,直接简化成:
msg: "{{ hostvars[target_hosts].my_fact }}"
另外,如果第一个Play的Fact是在localhost上设置的(比如生成动态inventory的操作通常在本地跑),那直接访问localhost的hostvars就行:
msg: "{{ hostvars['localhost'].my_fact }}"
方法二:用set_stats实现全局变量跨Play传递
如果你的my_fact不需要和特定主机绑定,只是单纯要把数据从第一个Play传到第二个Play,用set_stats比hostvars更省心——它会把变量存在Ansible的全局统计里,所有后续Play都能直接用。
第一个Play中设置全局变量
- name: 第一个Play:采集数据+设置全局变量+生成动态inventory hosts: "{{ target_hosts }}" tasks: - name: 采集数据并设置全局统计变量 set_stats: data: my_global_fact: "采集到的内容" per_host: false # 设为false就是全局变量,不绑定到单个主机
第二个Play中直接访问
- name: 第二个Play:使用动态inventory并访问全局变量 hosts: dynamic_inv_group tasks: - name: 直接调用全局变量 debug: msg: "{{ my_global_fact }}"
方案对比
hostvars:适合每个目标主机都有独立my_fact的场景,能保留主机和Fact的对应关系,但需要明确目标主机的标识(主机名/组名)。set_stats:适合全局共享的通用数据,不用处理主机关联的问题,写法更简洁。
错误排查小技巧
要是还是访问失败,先在第二个Play里打印所有hostvars内容,确认Fact有没有被正确创建:
- name: 打印所有hostvars内容排查 debug: var: hostvars delegate_to: localhost
内容的提问来源于stack exchange,提问作者piercjs
相关产品推荐
相关产品推荐

