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

Ansible能否在Play内条件设置目标主机?现有方案报错求助

问题描述

需求:当通过-e参数传入的perform_action值为telnet、curl、nslookup、traceroute、get_ip_address其中之一时,Play需运行在localhost;否则运行在remotehosts。

用户执行的命令:

ansible-playbook test.yml -e perform_action='nslookup'

对应的Playbook代码:

- name: "Play 1"
  hosts: localhost
  tasks:
    - set_fact:
        final_delegate: "{{ 'localhost' if perform_action in 'telnetcurlnslookuptracerouteget_ip_address' else 'remotehosts' }}    "

    - debug:
        msg: "Play needs to run on {{ final_delegate }}"

- name: "Play 2"
  hosts: "{{ final_delegate }}"
  tasks:
    - debug:
        msg: "Im running on {{ inventory_hostname }}"

执行结果:

  • Play1输出正常:
    The Play needs to run on localhost
    
  • Play2报错:
    ERROR! The field 'hosts' has an invalid value, which includes an undefined variable. The error was: 'final_delegate' is undefined
    

用户疑问:能不能在Play内部实现这个条件设置,还是只能通过-e参数传递条件?


解答

问题根源

set_fact在Play1里设置的变量,默认只存在于localhost的hostvars中。而Play2在解析hosts字段的时候,还没执行任何任务,没法直接读取到Play1里设置的变量,所以会报未定义的错误。

可行的实现方法

方法1:直接在Play2的hosts里写条件逻辑

不用依赖Play1的set_fact,直接把判断逻辑写在Play2的hosts字段里,Ansible解析Play的时候就能算出目标主机:

- name: "Play 2"
  hosts: "{{ 'localhost' if perform_action in ['telnet', 'curl', 'nslookup', 'traceroute', 'get_ip_address'] else 'remotehosts' }}"
  tasks:
    - debug:
        msg: "Im running on {{ inventory_hostname }}"

注意:原代码里perform_action in 'telnetcurlnslookuptracerouteget_ip_address'是错误的——字符串会被当成字符序列来匹配,必须用列表['telnet', 'curl', ...]才能准确判断值是否在目标集合里。

方法2:通过hostvars读取Play1的变量

如果一定要保留Play1的逻辑,可以在Play2的hosts里通过hostvars['localhost']['final_delegate']来读取localhost上的变量:

- name: "Play 1"
  hosts: localhost
  tasks:
    - set_fact:
        final_delegate: "{{ 'localhost' if perform_action in ['telnet', 'curl', 'nslookup', 'traceroute', 'get_ip_address'] else 'remotehosts' }}"

    - debug:
        msg: "Play needs to run on {{ final_delegate }}"

- name: "Play 2"
  hosts: "{{ hostvars['localhost']['final_delegate'] }}"
  tasks:
    - debug:
        msg: "Im running on {{ inventory_hostname }}"

方法3:通过-e参数传递结果

也可以在执行命令时直接算出目标主机并传入:

ansible-playbook test.yml -e "perform_action='nslookup' final_delegate=$(if [[ 'nslookup' =~ ^(telnet|curl|nslookup|traceroute|get_ip_address)$ ]]; then echo 'localhost'; else echo 'remotehosts'; fi)"

这种情况下,Play2可以直接用{{ final_delegate }}作为hosts的值。

结论

不是只能通过-e传递条件,直接在Play内部写条件表达式或者用hostvars读取变量的方式都能实现需求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 18:05:26