首页/系统与基础设施/自动化运维速查/失败判定与变更判定的重写用法
Ansible 核心70 条

失败判定与变更判定的重写用法

failed_when 与 changed_when 在控制节点对返回结果重新判定成败与变更:查询类命令可把可接受的非零码排除在失败之外,只读任务声明无变更,按输出判断是否真改动了内容。用它贴近语义而非掩盖故障,并注意变更信号与处理器的联动。

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌​​​​‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​‌‌​‌‌​‌​‌‌​​​​‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌‌‌​‌‌​​‌‌​​‌‌​​​​‌​‌‌​‌​​‌​‌‌​‌‌​​​‌‌​​‌​‌​‌‌​​‌​​​​‌​‌‌​‌​‌‌‌​‌‌‌​‌‌​‌​​​​‌‌​​‌​‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌​​​‌‌​‌‌​‌​​​​‌‌​​​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​‌​‌​‌‌​​‌​​​​‌​‌‌​‌​‌‌‌​‌‌‌​‌‌​‌​​​​‌‌​​‌​‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌‌​‌​‌​‌‌‌​​‌‌​‌‌​​​​‌​‌‌​​‌‌‌​‌‌​​‌​‌​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​

重写成败与变更判定

命令类任务默认按退出码判断失败、按“执行过”判断变更,这两条默认规则经常不符合实际语义:某个命令返回非零只是“没找到匹配项”,某个查询每次都被记为变更。失败判定与变更判定两个关键字允许在任务结果返回后、由控制节点重新判定,把语义纠正过来。

基本信息

失败判定覆盖默认退出码判断,条件成立即视为失败
变更判定覆盖默认“执行过即变更”的行为
求值位置在控制节点对返回结果求值,可引用输出内容与返回码
多条件写法条件以列表给出时按“任一成立”处理,需要同时成立时写成单个复合表达式
忽略错误忽略错误会让流程继续,但主机仍被标记为失败状态
日志抑制失败信息可能含敏感内容,必要时抑制输出

典型使用场景

  • 可接受的非零码:查询类命令无匹配时返回非零,不应判为故障
  • 只读命令:用变更判定声明无变更,避免污染变更统计与触发处理器
  • 有条件的变更:命令输出显示确实改了东西时才标记为变更
  • 容忍已知错误:环境上确实可能出现的报错降级为警告而不中断流程
  • 失败分级:按返回码区分致命错误与需要人工确认的中间状态
  • 与断言配合:先重写判定,再用断言校验关键字段

常见写法

常见写法
- name: 查询类命令:非零码不算失败
  ansible.builtin.command: grep -q enabled /etc/app/app.conf
  register: enabled_check
  failed_when: enabled_check.rc not in [0, 1]   # 0 命中、1 未命中都算正常
  changed_when: false

- name: 只读命令:显式声明无变更
  ansible.builtin.command: /usr/local/bin/app --version
  changed_when: false

- name: 按输出决定是否算变更
  ansible.builtin.shell: /usr/local/bin/sync-data.sh
  register: sync_out
  changed_when: "'updated' in sync_out.stdout"   # 没更新内容就不算变更

- name: 复合条件:两个条件都要满足才算失败
  ansible.builtin.command: /usr/local/bin/app --verify
  register: verify_out
  failed_when: verify_out.rc != 0 and 'EXPECTED' not in verify_out.stdout
  changed_when: false

- name: 失败判定重写为永不失败(谨慎)
  ansible.builtin.command: /usr/local/bin/may-fail.sh
  failed_when: false
  changed_when: false

用法与后果

写法用途风险
按返回码白名单判定把可接受的非零码排除在失败之外白名单放宽后真实错误被漏掉
变更判定为假只读任务不产生变更用在真实写操作上会掩盖变更
按输出判定变更有实质改动才标记变更输出措辞变化后判定失效
失败判定为假临时绕过已知问题长期保留会掩盖真实故障
忽略错误继续执行不让单点失败打断整批后续任务依赖上一步产物时会连锁失败
变更判定影响处理器触发:写成无变更后,依赖它的处理器不会再被触发。改动前先确认没有下游动作依赖这次变更信号,否则会出现“配置改了但服务没重载”的静默问题。
用永不失败或忽略错误来绕过报错属于应急手段:它让真实故障不再暴露,问题会在更晚、更难定位的位置出现。若必须临时使用,应留下显式的说明与后续处理计划,而不是长期保留在剧本里。

判断标准

重写判定前先问:这个命令的哪些返回码属于业务正常范围?它每次执行是否真的改了东西?把答案落到条件表达式里,再配合断言校验关键字段。重写是为了让判定贴近语义,而不是为了让流程看起来更顺利。

易错点

  • 把失败判定写成永不失败,真实故障被静默吞掉,问题在更晚的环节暴露
  • 对真实写操作声明无变更,依赖它的处理器不再触发,配置改了服务没重载
  • 按输出措辞判断变更或失败,日志文案随版本变化后判定失效
  • 多条件判定写成列表却期望“同时成立”,实际按任一成立处理
  • 用忽略错误让流程继续,后续任务因缺少上一步产物而连续失败,掩盖根因

数据来源与参考

  • Ansible 官方文档 Error handling in playbooks(failed_when、failed_when: false)
  • Ansible 官方文档 Defining changed(changed_when)
  • Ansible 官方文档 Handlers 与变更通知机制

整理校对:其其网ICT文档中心 · 本页地址:docs.qiqicto.com/automation/failed-when-changed-when-usage.html

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌​​​​‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​‌‌​‌‌​‌​‌‌​​​​‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌‌‌​‌‌​​‌‌​​‌‌​​​​‌​‌‌​‌​​‌​‌‌​‌‌​​​‌‌​​‌​‌​‌‌​​‌​​​​‌​‌‌​‌​‌‌‌​‌‌‌​‌‌​‌​​​​‌‌​​‌​‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌​​​‌‌​‌‌​‌​​​​‌‌​​​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​‌​‌​‌‌​​‌​​​​‌​‌‌​‌​‌‌‌​‌‌‌​‌‌​‌​​​​‌‌​​‌​‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌‌​‌​‌​‌‌‌​​‌‌​‌‌​​​​‌​‌‌​​‌‌‌​‌‌​​‌​‌​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​