Ansible:如何按值输出变量(层级变量优先级处理)
Ansible变量优先级逻辑修复
问题场景
尝试构建Ansible任务,实现列表项变量 > config.target全局变量 > 默认值的优先级逻辑:
- 列表项存在对应变量时,使用该项的值
- 列表项无对应变量时,使用config.target下的全局值
- 全局值也不存在时,使用预设默认值
但执行命令ansible-playbook ~/data/playbooks/test/_book.check-hosts.yml --extra-vars "@~/config.test.yml"后,缺失变量的位置直接输出变量名字符串(如host2的port输出config.target.port,host3的port、user、pass均输出变量名),未按预期取全局值或默认值。
原任务代码:
ansible.builtin.debug: msg: - "{{ item.name }}" - "{{ item.host }}" - "{{ item.port | config.target.port | default('22') }}" - "{{ item.user | config.target.user | default('root') }}" - "{{ item.pass | config.target.pass | default('SeCr3t') }}" with_items: "{{ config.target.list }}"
配置文件config.test.yml内容:
config: target: list: - name: host1 host: host1.vm.example.com port: 22 user: ansible pass: SuperMegaPass - name: host2 host: host2.vm.example.com user: ansible - name: host3 host: host3.vm.example.com port: 22 user: ansible pass: SuperMegaPass
错误原因
原代码中item.port | config.target.port的写法错误:Ansible的管道符|用于将左侧值传递给过滤器函数,但config.target.port并非过滤器,因此当item.port不存在时,管道符会直接将字符串config.target.port输出,而非读取该变量的实际值。
修复方案
使用default过滤器的嵌套写法,实现多层优先级判断:
- 第一层:
default(config.target.port, true)——当item.port未定义时,取config.target.port的值(第二个参数true表示仅在变量未定义时触发,而非空值) - 第二层:嵌套
default('22')——当config.target.port也未定义时,使用默认值
修正后的任务代码:
ansible.builtin.debug: msg: - "{{ item.name }}" - "{{ item.host }}" - "{{ item.port | default(config.target.port, true) | default('22') }}" - "{{ item.user | default(config.target.user, true) | default('root') }}" - "{{ item.pass | default(config.target.pass, true) | default('SeCr3t') }}" loop: "{{ config.target.list }}"
注:
with_items已被Ansible官方标记为过时,推荐使用loop替代。
验证结果
执行修复后的任务,输出符合预期:
- host1:所有变量使用列表项自身定义的值
- host2:port取全局
config.target.port的22,user用自身定义的ansible,pass取全局的SuperMegaPass - host3:port、user、pass均取全局对应值,若全局值不存在则使用默认值
内容的提问来源于stack exchange,提问作者Kris Weber
相关产品推荐
相关产品推荐

