先标记后执行
处理器是一类特殊任务:只有被通知、且被通知的那个任务本次确实产生了变更,它才会执行,默认在所有普通任务跑完之后统一执行一次。这套“先标记、后执行”的机制让重复重启被自动合并,也带来了两个高频困惑:处理器结果为什么总出现在最后、通知了为什么没有执行。把触发条件说清楚,多数疑问就能自己解释。
基本信息
| 触发方式 | 任务在发生变更时按名字通知处理器 |
|---|---|
| 默认时机 | 每个 play 的普通任务全部结束之后 |
| 生效条件 | 有通知,且通知它的任务状态为已变更 |
| 打破时机 | 用显式的元任务强制触发,或调整 play 结构 |
典型使用场景
- 改完配置后重载服务:避免每个改配置的任务都触发一次重载
- 多个任务改同一份配置:合并成一次重载,缩短服务中断窗口
- 需要立刻生效的场景:用强制触发方式执行,而不是等末尾
- 调试“通知了却没跑”:先确认任务是否真的产生了变更
- 多项服务按顺序重载:靠处理器的声明顺序排列
通知与强制触发
通知与强制触发
- name: 改配置 # 只有状态为已变更时才通知
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: reload nginx
- name: 需要立刻执行时强制触发 # 否则等到 play 末尾
ansible.builtin.meta: flush_handlers
# handlers 段(写在同一 play 内)
# - name: reload nginx
# ansible.builtin.service:
# name: nginx
# state: reloaded执行与否对照
| 情形 | 是否执行 | 原因 |
|---|---|---|
| 任务有变更并通知 | 执行 | 通知与变更两个条件都满足 |
| 任务无变更 | 不执行 | 没有变更就不会触发 |
| 通知名不匹配 | 不报错也不执行 | 找不到对应处理器 |
| play 中途失败 | 可能不执行 | 默认在普通任务之后阶段运行 |
处理器的输出集中在末尾出现,不代表它在末尾才被决定:通知在任务执行时就已经登记,只是统一放到阶段末尾运行。看输出顺序时别被位置误导。
用强制触发打破默认顺序后,后面再发生的变更会再触发一次,服务可能被重载两次。确认影响范围后再使用,尤其是重启类动作。
失败与时机的关系
默认时机在普通任务之后,所以 play 中途失败时处理器可能根本没有机会运行,结果是配置改了但服务没重载,机器处在中间状态。对顺序敏感的变更,可以把不可预演或可能失败的任务放在重载之前,并在关键步骤后强制触发一次,缩小不一致窗口。