Ansible动态HTML邮件模板构建问题求助
解决Ansible补丁管理邮件模板的汇总问题
核心思路是先聚合所有目标主机的信息到本地,再单次渲染模板发送邮件,避免run_once导致的信息不全或无run_once导致的重复发送问题。
方案一:提前聚合主机信息到本地变量
Playbook示例
--- - name: 收集服务器补丁信息并发送汇总邮件 hosts: all gather_facts: yes tasks: # 1. 收集每台服务器的关键信息(这里以系统信息+补丁数量为例) - name: 检查可更新补丁数量 ansible.builtin.command: yum check-update --quiet | grep -v "^Obsoleting" | wc -l register: pending_updates changed_when: false args: warn: false # 针对Debian/Ubuntu系统替换为:apt list --upgradable 2>/dev/null | grep -v "^Listing" | wc -l # 2. 将每台主机的信息追加到本地(localhost)的全局列表中 - name: 聚合服务器信息 ansible.builtin.set_fact: server_report_data: "{{ server_report_data | default([]) + [ { 'hostname': inventory_hostname, 'os': ansible_distribution, 'os_version': ansible_distribution_version, 'pending_updates': pending_updates.stdout } ] }}" delegate_to: localhost run_once: false # 每台主机都执行,把自身信息加入本地列表 # 3. 单次渲染模板并发送邮件 - name: 发送汇总邮件 ansible.builtin.mail: subject: "服务器补丁管理汇总报告" body: "{{ lookup('template', 'patch_report.j2') }}" from: "ansible-monitor@your-domain.com" to: "admin-team@your-domain.com" subtype: html delegate_to: localhost run_once: true # 仅在本地执行一次,用聚合好的列表渲染模板
Jinja2模板(patch_report.j2)
<html> <head> <style> table { border-collapse: collapse; width: 90%; margin: 20px auto; } th { background: #f0f0f0; padding: 10px; border: 1px solid #ddd; } td { padding: 8px; border: 1px solid #ddd; } .header { text-align: center; color: #333; } </style> </head> <body> <h2 class="header">服务器补丁管理汇总</h2> <table> <tr> <th>主机名</th> <th>操作系统</th> <th>系统版本</th> <th>待更新补丁数</th> </tr> {% for server in server_report_data %} <tr> <td>{{ server.hostname }}</td> <td>{{ server.os }}</td> <td>{{ server.os_version }}</td> <td>{{ server.pending_updates }}</td> </tr> {% endfor %} </table> </body> </html>
方案二:直接在模板中遍历所有主机变量
如果不想提前聚合,可以直接在Jinja2模板中通过hostvars访问所有目标主机的信息,Playbook会更简洁:
简化版Playbook
--- - name: 收集服务器信息并发送汇总邮件 hosts: all gather_facts: yes tasks: - name: 检查可更新补丁数量 ansible.builtin.command: yum check-update --quiet | grep -v "^Obsoleting" | wc -l register: pending_updates changed_when: false args: warn: false - name: 发送汇总邮件 ansible.builtin.mail: subject: "服务器补丁管理汇总报告" body: "{{ lookup('template', 'patch_report_simple.j2') }}" from: "ansible-monitor@your-domain.com" to: "admin-team@your-domain.com" subtype: html delegate_to: localhost run_once: true
简化版Jinja2模板(patch_report_simple.j2)
<html> <head> <style> table { border-collapse: collapse; width: 90%; margin: 20px auto; } th { background: #f0f0f0; padding: 10px; border: 1px solid #ddd; } td { padding: 8px; border: 1px solid #ddd; } .header { text-align: center; color: #333; } </style> </head> <body> <h2 class="header">服务器补丁管理汇总</h2> <table> <tr> <th>主机名</th> <th>操作系统</th> <th>系统版本</th> <th>待更新补丁数</th> </tr> {% for host in groups['all'] %} <tr> <td>{{ host }}</td> <td>{{ hostvars[host]['ansible_distribution'] }}</td> <td>{{ hostvars[host]['ansible_distribution_version'] }}</td> <td>{{ hostvars[host]['pending_updates']['stdout'] }}</td> </tr> {% endfor %} </table> </body> </html>
问题根源说明
- 你之前设置
run_once: true时,邮件任务仅在第一台目标主机上执行,此时只能访问该主机的本地变量,无法获取其他主机的信息,导致模板循环只填充第一台数据。 - 移除
run_once后,每台主机都会执行邮件任务,若模板未处理全局变量,会重复发送仅包含当前主机信息的邮件(或因变量作用域问题导致内容重复)。
内容的提问来源于stack exchange,提问作者SwiperNo
相关产品推荐
相关产品推荐

