今天给大家总结生产环境最常用、最核心的 Ansible 高级任务控制机制: Handler 触发器、任务失败忽略、强制触发 Handler、自定义失败条件、任务块 block/rescue/always。
这些知识点不是考试考点那么简单,是企业自动化运维每天都在用的保命技能,一定要吃透!
一、Handler 程序:只有被通知才会跑的 “懒人任务”
1. 什么是 Handler?
Handler 可以理解为:非活动任务,平时不执行,只有被 notify 显式调用时才触发。
特点(生产必记):
- 默认在 Play 中所有普通任务执行完成后才运行
- 多个任务通知同一个 Handler,只会运行一次
- 没有任务通知,就绝对不运行
- 最常用场景:修改配置后重启服务、部署完成后重启主机
2. 简单示例(一看就懂)
– name: 部署 Nginx
hosts: web
tasks:
– name: 拷贝 Nginx 配置文件
copy:
src: nginx.conf
dest: /etc/nginx/nginx.conf
notify: 重启 Nginx # 通知 Handler
handlers:
– name: 重启 Nginx # 名字必须和 notify 完全一致
service:
name: nginx
state: restarted
3. 核心结论
配置变更 → 通知重启 → 所有任务跑完 → 仅重启一次 这就是企业标准化服务管理的标准姿势。
4. 超级大坑
默认行为:任务一旦报错 → Play 立即中断 → Handler 永远不执行!
tasks:
– name: 替换MySQL配置
copy:
src: my.cnf
dest: /etc/my.cnf
notify: 重启MySQL
– name: 这里故意出错
shell: /bin/false
handlers:
– name: 重启MySQL
service: name=mysql state=restarted
结果:
配置改了 → 任务报错 → Play 中断 → Handler 不执行!
MySQL 不会重启!配置不生效!
这就是生产事故隐患!
解决方法:force_handlers: yes(下文将会讲到)
二、任务失败处理:让 Play 不中断、不卡死
1. 默认行为
任何一个任务失败 → Play 直接中止 → 后面任务全部不执行
生产环境非常不友好!
三、ignore_errors:忽略任务失败
作用
即使当前任务失败,继续执行后面的任务。
使用方式
– name: 执行一个可能失败的命令
shell: /bin/false
ignore_errors: yes # 忽略失败,继续跑
生产场景
- 检查某个文件是否存在(不存在也不影响流程)
- 清理临时文件(已清理也不报错)
- 非关键步骤不阻塞主流程
四、force_handlers:任务失败了,也要强制执行 Handler
重点!
默认:通知 Handler 的任务失败 → Handler 被跳过,不执行!
这会导致: 配置改了 → 任务中途炸了 → 服务没重启 → 环境不一致!
解决:force_handlers: yes
– name: 强制触发 Handler
hosts: web
force_handlers: yes # 关键!任务失败也会执行 Handler
tasks:
– name: 修改配置
copy: src=xxx dest=xxx
notify: 重启服务
– name: 故意失败
shell: /bin/false
handlers:
– name: 重启服务
service: name=xxx state=restarted
✅ force_handlers 是 PLAY 属性
✅ 必须写在 tasks 前面
✅ 不能写在 tasks 后面!不然后面不生效!
生产意义
哪怕中间步骤炸了,服务也必须重启,保证配置生效!
五、failed_when:自定义任务失败条件
作用
任务执行成功了,但我想让它根据业务逻辑判定为失败。
示例
– name: 检查业务状态
shell: curl -s http://localhost/health
register: result
failed_when: "'ok' not in result.stdout"
解释
- 命令执行成功(返回码 0)
- 但返回内容不包含 ok → Ansible 判定任务失败
生产场景
- 业务端口检查
- 接口健康检查
- 配置文件语法检查
- 自定义业务校验
六、block /rescue/always:Ansible 的 “try-catch”
三个关键字
- block:正常要执行的任务
- rescue:block 失败时才执行
- always:无论成功失败,永远执行
示例:MySQL 升级失败 → 自动回滚旧版本软链接
– name: MySQL 升级 + 失败自动回滚
hosts: db
become: yes
tasks:
– name: MySQL 升级主逻辑
block:
– name: 停止MySQL
service: name=mysql state=stopped
– name: 创建新版本软链接
file:
src: /usr/local/mysql-8.0.39
dest: /usr/local/mysql
state: link
– name: 启动MySQL新版本
service: name=mysql state=started
– name: 检查MySQL是否正常运行
shell: mysql -V
register: mysql_ver
rescue:
– name: 升级失败!自动回滚旧版本软链接
file:
src: /usr/local/mysql-8.0.36
dest: /usr/local/mysql
state: link
– name: 重启旧版本MySQL
service: name=mysql state=restarted
– name: 发送告警
debug: msg="MySQL 升级失败,已自动回滚!"
always:
– name: 无论成功失败,记录日志
debug: msg="MySQL 升级流程执行完毕"
生产意义
- 部署失败 → 自动回滚
- 无论成功失败 → 发钉钉 / 邮件通知
- 流程可控、可自愈、可监控
七、生产环境总结(超级重要)
我把今天所有内容浓缩成企业运维必背 6 条:
这 6 个功能,是生产环境 Ansible 自动化的灵魂!
八、学习心得
学 Ansible 不要只学基础模块,任务流程控制、异常处理、服务重启机制才是企业真正用得上的东西。
今天讲的这些,你在 RH294、生产自动化、K8s 部署、CI/CD 里都会天天遇到。
如果你也在学 Ansible 运维自动化,欢迎点赞 + 收藏 + 关注,我会持续更新小白能看懂、企业能直接用的实战文章!





