Ansible批量主机blkid检查后合并发送失败主机邮件求助
解决Ansible多主机blkid检查失败时汇总发邮件的问题
我来帮你搞定这个问题!你的核心困扰是当前每台失败的主机会单独触发一封邮件,这是因为原代码里的rescue块会在单个主机执行失败时立刻触发邮件发送逻辑。要实现「汇总所有失败主机发单封邮件」的需求,我们需要调整思路:先让所有主机完成检查,统一收集失败节点信息,最后在控制节点上一次性发送汇总邮件。
修改后的完整main.yml代码
- name: 执行所有主机的blkid检查 hosts: all gather_facts: false tags: checkblkid tasks: - name: 运行blkid命令 shell: /sbin/blkid register: blkid_result failed_when: blkid_result.rc != 0 ignore_errors: true # 关键:即使单台主机失败,也继续检查其他主机,不中断整个任务 - name: 发送失败主机汇总邮件 hosts: localhost gather_facts: false tags: checkblkid tasks: - name: 收集所有blkid检查失败的主机 set_fact: failed_hosts: "{{ groups['all'] | select('in', hostvars | dict2items | selectattr('value.blkid_result.failed') | map(attribute='key') | list) }}" - name: 当存在失败主机时发送汇总邮件 mail: host: localhost to: xxxx@gmail.com subject: blkid检查失败主机列表 subtype: html body: | <h3>以下主机blkid检查失败:</h3> <ul> {% for host in failed_hosts %} <li>{{ host }}</li> {% endfor %} </ul> when: failed_hosts | length > 0 # 只有有失败主机时才发送邮件
代码逻辑说明
第一阶段:全量执行检查
- 针对所有主机执行
blkid命令,用register记录每台主机的执行结果 ignore_errors: true确保某台主机失败时,Ansible不会终止整个任务,而是继续检查剩余主机failed_when依然会标记执行失败的主机,方便后续筛选
- 针对所有主机执行
第二阶段:汇总并发送邮件
- 在控制节点(localhost)上,通过
hostvars遍历所有主机的执行结果,筛选出blkid_result.failed为true的主机 - 用Jinja2模板在邮件正文中生成失败主机的HTML列表,让邮件内容更清晰
- 添加
when条件,只有存在失败主机时才发送邮件,避免发送空内容的邮件
- 在控制节点(localhost)上,通过
对比原代码的改进点
原代码的rescue块属于单主机级别的错误处理,每台主机失败都会独立触发邮件发送;新方案是先完成所有主机的检查,再统一汇总失败信息,从「单主机触发」变成「全局汇总触发」,完美解决了多封邮件的问题。
内容的提问来源于stack exchange,提问作者avis8960




