Ansible:使用ignore_errors时如何在Play Recap中统计失败任务数
用Ansible实现批量服务器验证检查:全失败收集+正确统计失败数
我之前帮客户做过类似的批量服务器巡检/验证场景,刚好可以给你一套落地的方案,完美解决你的两个核心需求:不中途终止、收集所有失败结果,同时确保Play Recap正确统计失败任务数。
核心思路拆解
你的需求本质是:
- 单台主机上的所有验证任务必须执行完毕,哪怕前面的任务失败
- 所有失败的任务都要被标记为「失败」,不能因为忽略错误而不统计到Play Recap里
下面给你两种实用方案,根据你的Ansible版本选择:
方案一:Ansible 2.15+ 专属(推荐,更直观)
Ansible 2.15新增了continue_on_error参数,允许单台主机上的某个任务失败后,继续执行该主机的后续任务,同时不会影响失败任务的统计——也就是说,失败的任务依然会被计入Play Recap的failed计数里,完全符合你的需求。
示例剧本
- name: 批量服务器验证检查 hosts: all gather_facts: yes # 开头自动收集系统基础信息,也可以用setup模块自定义收集 tasks: # 可选:收集自定义信息(比如只收集IP相关) - name: 收集主机IP信息 setup: filter: ansible_*_ipv4 # 验证任务1:检查SSH服务是否启动 - name: 验证SSH服务运行状态 service: name: sshd state: started register: sshd_check failed_when: sshd_check.state != "started" # 自定义失败条件 continue_on_error: true # 失败后继续执行当前主机的下一个任务 # 验证任务2:检查根分区磁盘使用率不超过80% - name: 验证根分区磁盘使用率 shell: df -h / | awk 'NR==2 {print $5}' | sed 's/%//' register: disk_usage_check failed_when: disk_usage_check.stdout | int > 80 continue_on_error: true # 验证任务3:检查剩余内存不低于1GB - name: 验证剩余内存 shell: free -g | awk '/Mem:/ {print $4}' register: mem_free_check failed_when: mem_free_check.stdout | int < 1 continue_on_error: true
方案二:兼容所有Ansible版本(通用方案)
如果你的Ansible版本低于2.15,可以用block+ignore_errors的组合,既能让单台主机的所有验证任务执行完毕,又能保证失败任务被正确统计。
示例剧本
- name: 批量服务器验证检查 hosts: all gather_facts: yes tasks: # 收集自定义信息(可选) - name: 收集主机硬件信息 setup: filter: ansible_processor_vcpus, ansible_memtotal_mb # 用block包裹所有验证任务,统一控制错误处理 - block: - name: 验证SSH服务运行状态 service: name: sshd state: started register: sshd_check failed_when: sshd_check.state != "started" - name: 验证根分区磁盘使用率 shell: df -h / | awk 'NR==2 {print $5}' | sed 's/%//' register: disk_usage_check failed_when: disk_usage_check.stdout | int > 80 - name: 验证剩余内存 shell: free -g | awk '/Mem:/ {print $4}' register: mem_free_check failed_when: mem_free_check.stdout | int < 1 ignore_errors: true # 允许block内任务失败,但继续执行后续任务 rescue: [] # 空rescue,不做错误恢复,只保留失败状态
关键说明
这个方案的核心是:block内的每个任务失败后,Ansible会继续执行block内的其他任务,同时每个失败的任务都会被正常标记为failed,Play Recap会正确统计失败数——这和直接给单个任务加ignore_errors: true的区别很大,单个任务加ignore_errors会让失败被忽略,不会计入Play Recap的failed计数。
可选:汇总所有失败结果
如果你需要在剧本结束后,一次性看到所有主机的失败任务汇总,可以添加一个任务:
- name: 汇总所有验证失败结果 debug: msg: | 🚨 主机 {{ inventory_hostname }} 验证失败任务清单: {% for task in ansible_failed_result.results if task is failed %} - 任务名称:{{ task.name }} 失败原因:{{ task.msg | default('无详细信息') }} {% else %} ✅ 所有验证任务通过 {% endfor %} when: ansible_failed_result is defined or ansible_failed_result is not defined
这个任务会在每台主机上输出验证结果,成功的主机显示通过,失败的主机列出所有失败的任务和原因。
注意事项
- 优先使用Ansible原生模块(比如
service、stat)做验证,尽量避免shell/command模块,原生模块更可靠,且不会产生不必要的changed状态。 - 如果不需要收集所有系统信息,可以用
gather_facts: no,然后用setup模块过滤需要的变量,提升剧本执行速度。 - 如果你需要把失败结果导出到文件,可以用
copy模块把debug的结果写入到本地文件,比如:- name: 导出失败结果到本地文件 copy: content: | 主机 {{ inventory_hostname }} 验证失败任务: {% for task in ansible_failed_result.results if task is failed %} - {{ task.name }}: {{ task.msg | default('无详细信息') }} {% endfor %} dest: "./failed_checks_{{ inventory_hostname }}.log" delegate_to: localhost when: ansible_failed_result is defined
内容的提问来源于stack exchange,提问作者ebrewer
相关产品推荐
相关产品推荐

