Ansible中如何基于inventory_hostname匹配字典设置跨剧本可用变量?
问题描述
之前我通过匹配主机名特定字符、用字典映射设置变量的逻辑完成过需求,现在复用相同逻辑时遇到两个问题:
- 主剧本导入两个子剧本后,变量无法跨剧本调用
- 能正确提取主机名目标位置的字符,却无法匹配字典中对应的键值
此前的实现(SCRIPT1.yml)
通过environmentlist.yml变量文件,基于主机名第4个字符(索引3)匹配字典值设置变量:
myvar_dict: p: Production s: Staging t: Test default: Sales myvar: "{{ myvar_dict[inventory_hostname.3]|default(myvar_dict.default) }}"
当前需求与问题(SCRIPT2.yml)
使用otherlist.yml变量文件,基于主机名第9个字符(索引8)匹配字典值设置变量:
myvar2_dict: S: VALUE1 1: VALUE2 2: VALUE3 3: VALUE4 4: VALUE5 5: VALUE6 default: VALUE1 myvar2: "{{ myvar2_dict[inventory_hostname.8]|default(myvar2_dict.default) }}"
主机列表示例
000p00002hostname 000t0000Shostname 000s00005hostname
具体问题
- 主剧本导入SCRIPT1和SCRIPT2后,SCRIPT2中无法调用SCRIPT1定义的
myvar变量 - 执行SCRIPT2时,能正确提取主机名对应位置的字符(比如第一个主机提取到"2"),但报错找不到字典中对应的键值
我尝试把变量定义从外部文件移到剧本内部,问题依然存在。
期望目标
最终要基于myvar和myvar2生成新变量,示例逻辑如下:
tasks: - name: 确定服务器对应的Spacewalk组 set_fact: MYGROUPVAR: "{{ myvar }} {{ myvar2 }}" - name: 执行脚本 script: script.py "{{ inventory_hostname }}" "{{ MYGROUPVAR }}"
解决方案
问题1:变量跨剧本无法留存
Ansible中,import_playbook导入的子剧本是独立play,变量默认不会在不同play间共享。解决方法二选一:
- 用
set_fact加上cacheable: yes标记,将变量存入fact缓存,实现跨play共享 - 把两个剧本的变量定义合并到同一个变量文件,在主剧本中统一加载,避免跨play变量传递问题
示例:修改SCRIPT1用set_fact缓存变量
# SCRIPT1.yml - hosts: all vars_files: - environmentlist.yml tasks: - name: 设置myvar并缓存 set_fact: myvar: "{{ myvar_dict[inventory_hostname.3]|default(myvar_dict.default) }}" cacheable: yes
问题2:字典键值匹配失败
字典中的数字键(如1、2)是整数类型,但从主机名提取的字符是字符串类型,类型不匹配导致无法匹配。解决方法二选一:
- 把字典中的数字键改为字符串形式,统一键的类型
- 若提取的字符确保是数字,可将其转为整数后再匹配(但提取字符为字母时会报错,不推荐)
修改后的otherlist.yml(推荐方案):
myvar2_dict: "S": VALUE1 "1": VALUE2 "2": VALUE3 "3": VALUE4 "4": VALUE5 "5": VALUE6 "default": VALUE1 myvar2: "{{ myvar2_dict[inventory_hostname.8]|default(myvar2_dict.default) }}"
内容的提问来源于stack exchange,提问作者Drazor
相关产品推荐
相关产品推荐

