Ansible基于条件调用缓存OS facts遇'system'未定义错误的排查
问题场景
我使用以下Playbook基于ansible_system事实收集特定OS信息:
--- - name: Gather facts from all target hosts hosts: all gather_facts: false tasks: - name: Gather OS information for linux set_fact: os_version: "{{ ansible_facts[distribution] }} {{ ansible_facts[distribution_version] }}" when: ansible_facts[system] == "Linux" - name: Gather OS information for Windows set_fact: os_version: "{{ ansible_facts[ansible_os_name] }}" when: ansible_facts[system] is search("Win") - name: Set unknowm if not linux or windows set_fact: os_version: 'unknown' when: - not ansible_facts[system] is search("Win") - not ansible_facts[system] == "Linux"
报错信息
所有清单内主机均出现如下错误:
"msg": "The conditional check 'ansible_facts[system] == "Linux"' failed. The error was: error while evaluating conditional (ansible_facts[system] == "Linux"): 'system' is undefined."
缓存事实示例
经核查,报错主机均存在缓存的ansible_system事实,示例如下:
"ansible_system": "Linux", "ansible_cmdline": { "ro": true, "root": "UUID=fcd2fe34-d0d2-4d03-8c17-0a5d8e61cfee", "BOOT_IMAGE": "/boot/vmlinuz-5.4.0-193-generic", "maybe-ubiquity": true }
疑问
我认为可以通过ansible_facts[system] == "Linux"或ansible_system == "Linux"两种方式访问该事实,请问是否是访问方式有误?
问题分析与修正
核心错误点
语法错误:字典键的访问方式
原Playbook中ansible_facts[system]的写法错误——这里的system会被当作变量解析,但你并未定义这个变量,因此触发“'system' is undefined”报错。
正确的字典访问方式有两种:- 字符串键索引:
ansible_facts['system'] - 点语法:
ansible_facts.system
- 字符串键索引:
gather_facts: false导致ansible_facts字典为空
你在Playbook中设置了gather_facts: false,Ansible不会主动收集新的事实,此时ansible_facts字典是空的。而缓存的事实是以ansible_*开头的独立全局变量存在的(比如ansible_system、ansible_distribution),直接调用这些变量即可,无需通过ansible_facts字典。其他变量访问错误
原Playbook中ansible_facts[distribution]、ansible_facts[distribution_version]、ansible_facts[ansible_os_name]均存在相同语法错误,需对应修正为独立变量或正确的ansible_facts访问方式。
修正后的Playbook
方案一:使用缓存的事实(无需重新收集)
--- - name: Gather facts from all target hosts hosts: all gather_facts: false tasks: - name: Gather OS information for Linux set_fact: os_version: "{{ ansible_distribution }} {{ ansible_distribution_version }}" when: ansible_system == "Linux" - name: Gather OS information for Windows set_fact: os_version: "{{ ansible_os_name }}" when: ansible_system is search("Win") - name: Set unknown if not Linux or Windows set_fact: os_version: 'unknown' when: - ansible_system is not search("Win") - ansible_system != "Linux"
方案二:重新收集事实(去掉gather_facts: false)
--- - name: Gather facts from all target hosts hosts: all # 默认gather_facts: true,可省略 tasks: - name: Gather OS information for Linux set_fact: os_version: "{{ ansible_facts.distribution }} {{ ansible_facts.distribution_version }}" when: ansible_facts.system == "Linux" - name: Gather OS information for Windows set_fact: os_version: "{{ ansible_facts.os_name }}" when: ansible_facts.system is search("Win") - name: Set unknown if not Linux or Windows set_fact: os_version: 'unknown' when: - ansible_facts.system is not search("Win") - ansible_facts.system != "Linux"
内容的提问来源于stack exchange,提问作者J1raya

