Ansible访问字典值返回空列表,未获取预期值问题咨询
问题
编写了如下Ansible主Playbook,通过vars_files引入environment-mapping.yml变量文件,其中controller_ip_environment_map字典包含XX.XXX.X.Y对应DEV的键值对。执行Playbook后,已正确获取controller_ip为XX.XXX.X.Y,但通过controller_ip_environment_map[controller_ip]取值时,environment变量却得到空列表[],而非预期的DEV,请问该问题原因是什么?
主Playbook代码
- hosts: localhost vars_files: - ../vars/environment-mapping.yml tasks: - name: echo and register controller's ip ansible.builtin.shell: cmd: | echo "$(hostname -I)" | sed 's/\s*$//' register: bash_echoed__controller_ip - name: set controller_ip_stringified set_fact: controller_ip: "{{ bash_echoed__controller_ip.stdout }}" - name: set environment set_fact: environment: "{{ controller_ip_environment_map[controller_ip] | default('unknown') }}" - name: show debug debug: msg: - "controller_ip_environment_map: {{ controller_ip_environment_map }}" - "controller_ip: {{ controller_ip }}" - "environment: {{ environment }}"
变量文件../vars/environment-mapping.yml代码
--- controller_ip_environment_map: { "XX.XXX.X.Y": "DEV", "XX.XXX.X.W": "TEST", "XX.XXX.X.Z": "PROD", }
执行结果
- localhost on hosts: localhost - Gathering Facts... localhost ok echo and register controller's ip... localhost done | stdout: XX.XXX.X.Y set controller_ip_stringified... localhost ok set environment... localhost ok show debug... localhost ok: { "changed": false, "msg": [ "controller_ip: XX.XXX.X.Y", "controller_ip_environment_map: {'XX.XXX.X.Y': 'DEV', 'XX.XXX.X.W': 'TEST', 'XX.XXX.X.Z': 'PROD'}", "environment: []", ] }
问题原因
核心有两个问题:
- 内置变量冲突:
environment是Ansible的内置魔法变量,本身是列表类型,用于存储执行环境相关变量。尝试用自定义值覆盖它时会触发异常行为,无法正确赋值,最终返回内置变量的默认空列表。 - IP字符串可能含隐藏空白:虽然
hostname -I输出看起来是干净的IP,但实际可能包含不可见的空白字符(比如换行符、残留空格),即使通过sed处理也可能没彻底清除,导致controller_ip的值和字典中的键不完全匹配。
解决方案
1. 更换自定义变量名
停止使用environment作为变量名,改用其他名称,比如target_env:
- name: set target environment set_fact: target_env: "{{ controller_ip_environment_map[controller_ip] | default('unknown') }}"
2. 可靠获取IP地址
放弃Shell命令获取IP,改用Ansible内置事实变量,更稳定且无隐藏字符:
- name: set controller_ip using ansible fact set_fact: controller_ip: "{{ ansible_default_ipv4.address }}"
如果必须用Shell命令,彻底清理所有空白:
- name: echo and register controller's ip ansible.builtin.shell: cmd: hostname -I | awk '{print $1}' register: bash_echoed__controller_ip
3. 验证字符串一致性
添加任务检查controller_ip的实际内容,确认无隐藏字符:
- name: check controller_ip content debug: msg: - "IP length: {{ controller_ip | length }}" - "IP raw content: {{ controller_ip | to_json }}"
内容的提问来源于stack exchange,提问作者Tms91
相关产品推荐
相关产品推荐

