force_handlers: yes 仅允许任务失败后仍执行已 notify 的 handler,而非自动清理;需配合预定义的清理 handler 和显式 notify 才能实现失败时清理。

在Ansible中,force_handlers 本身并不用于“部署失败时执行清理”,它只控制:当某个任务失败后,是否仍触发此前已 notify 的 handler。真正实现“失败时强制清理”,需要结合 force_handlers: yes + 显式定义的清理 handler + 合理的任务组织逻辑。
明确 force_handlers 的作用边界
它不是“自动运行清理”,而是解除默认限制——Ansible 默认一旦任务失败,整个 play 中断,所有未执行的 handler(哪怕已被 notify)都会被跳过。force_handlers: yes 只是让这些已通知的 handler 有机会被执行,前提是它们已被前面的任务调用 notify。
构建可触发的清理 handler
清理操作必须提前定义为 handler,并由某个任务显式通知。常见做法是:
- 把清理动作(如删除临时目录、回滚配置、停止测试服务)写成独立的 handler
- 在部署任务之前或中间,用
notify:提前绑定该清理 handler - 确保该 notify 出现在可能失败的任务之前(否则无法触发)
示例:
- name: Prepare temp dir
file:
path: /tmp/deploy_{{ ansible_date_time.epoch }}
state: directory
notify: cleanup_temp_dir
<ul><li>name: Deploy app (may fail)
copy:
src: app.tar.gz
dest: /opt/app/<h1>此处不加 ignore_errors,允许失败</h1></li></ul><p>handlers:</p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/xiazai/skill8828" title="Obsidian (Linux)"><img
src="https://img.php.cn/upload/skill/000/000/081/179228531040284.jpg" alt="Obsidian (Linux)" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/xiazai/skill8828" title="Obsidian (Linux)">Obsidian (Linux)</a>
<p>操作 Obsidian 库(纯 Markdown 笔记),并通过 notesmd-cli 实现自动化。</p>
</div>
<a href="/xiazai/skill8828" title="Obsidian (Linux)" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div><ul><li>name: cleanup_temp<em>dir
file:
path: /tmp/deploy</em>*
state: absent
启用 force_handlers 并验证执行路径
在 play 根级别声明 force_handlers: yes,确保即使部署任务失败,上面的 cleanup_temp_dir 依然运行:
---
- hosts: app_servers
force_handlers: yes # 关键:允许失败后仍跑 handler
tasks:
- name: Prepare temp dir
file:
path: /tmp/deploy_{{ ansible_date_time.epoch }}
state: directory
notify: cleanup_temp_dir
<pre class="brush:php;toolbar:false;">- name: Fail intentionally for test
command: /bin/false # 模拟部署失败
运行后,你会看到:Fail intentionally... 报错,但紧接着 cleanup_temp_dir 仍被执行。
补充:更健壮的清理建议
仅靠 force_handlers 不够可靠,推荐叠加以下实践:
- 使用 block + rescue:把部署步骤放入 block,失败时进 rescue 区块统一清理,语义更清晰、控制更精准
- 清理 handler 加 idempotent 判断:例如先检查目录是否存在再删除,避免清理时自身报错中断
-
关键清理动作不依赖 notify:对必须执行的清理(如释放锁、关闭端口),可放在最后 tasks 中,用
ignore_errors: yes+when: ansible_failed_result is defined判断上下文

















