You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ansible:使用ignore_errors时如何在Play Recap中统计失败任务数

用Ansible实现批量服务器验证检查:全失败收集+正确统计失败数

我之前帮客户做过类似的批量服务器巡检/验证场景,刚好可以给你一套落地的方案,完美解决你的两个核心需求:不中途终止、收集所有失败结果,同时确保Play Recap正确统计失败任务数。

核心思路拆解

你的需求本质是:

  1. 单台主机上的所有验证任务必须执行完毕,哪怕前面的任务失败
  2. 所有失败的任务都要被标记为「失败」,不能因为忽略错误而不统计到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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 10:11:05