You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 00:01:15