Ansible:结合条件语句使用copy模块无法正确写入目标主机名
问题分析与解决方案
核心问题排查
set_fact条件无效:原Playbook中when: certData.json > 0是错误判断——certData.json是字典类型,无法直接与数字比较,导致该任务始终跳过,activeCertData变量从未被定义,后续循环判断时会出现变量不存在的异常。- 未处理变量缺失场景:循环中直接访问
hostvars[host]['activeCertData'],若变量未定义会触发错误,无法正确识别符合条件的主机。
调整后的Playbook代码
--- - hosts: all gather_facts: false tasks: - name: Print certData.json debug: msg: "{{ certData.json }}" - name: Set activeCertData with JMESPATH set_fact: activeCertData: "{{ certData.json | json_query('items[?status != `revoked`].{ currentCertID: id, currentCertSN: serialHex, status: status, cn: cn}') }}" # 修正条件:判断证书数据中存在有效条目 when: certData.json.items | length > 0 - name: Generate new devices list file copy: dest: newDevices.txt content: |- {% for host in ansible_play_hosts %} {# 处理activeCertData未定义的情况,默认返回空列表 #} {% if hostvars[host].get('activeCertData', []) | length == 0 %} {{ host }} {% endif %} {% endfor %} delegate_to: localhost run_once: true
关键调整说明
- 修正变量赋值触发条件:改用
certData.json.items | length > 0判断证书数据中是否存在条目,确保activeCertData变量能被正确赋值。 - 安全访问变量:使用
hostvars[host].get('activeCertData', [])替代直接索引,当变量未定义时自动返回空列表,既避免报错又保证判断逻辑准确。 - 逻辑验证:以示例中的A01主机为例,其证书
status为Active-Pending Install(不属于revoked),因此activeCertData长度为1,不会被写入文件;若主机无有效证书(items为空或所有条目status为revoked),则会被正确写入文件。
如果需要追加符合条件的主机而非覆盖文件,可将copy模块替换为lineinfile模块:
- name: Append new devices to file lineinfile: path: newDevices.txt line: "{{ inventory_hostname }}" create: true delegate_to: localhost when: hostvars[inventory_hostname].get('activeCertData', []) | length == 0
此方式会让每个符合条件的主机单独执行任务,将自身主机名追加到文件中。
内容的提问来源于stack exchange,提问作者stminion001
相关产品推荐
相关产品推荐

