使用Ansible Playbook批量查询Windows更新,如何生成单份汇总报告?
解决Ansible多主机Windows更新报告重复生成问题
问题根源在于当前Playbook会在每台目标主机上执行win_template任务,导致每台主机都生成一份报告。要实现单份汇总报告,核心思路是只在一个节点(通常是控制节点localhost)执行一次报告生成任务,并收集所有主机的更新数据进行汇总。
方案一:拆分Play,分离数据收集与报告生成
将任务拆分为两个独立的Play:第一个Play在所有Windows主机上收集更新信息,第二个Play仅在控制节点生成汇总报告,逻辑清晰易维护。
修改后的Playbook代码
# 第一部分:在所有Windows主机上收集更新信息 - name: Collect Windows update status from all hosts hosts: windows_hosts tasks: - name: Search for pending Windows Updates ansible.windows.win_updates: category_names: '*' server_selection: "windows_update" state: searched register: check_win_updates_patchresult # 第二部分:在控制节点生成汇总HTML报告 - name: Generate consolidated update report hosts: localhost gather_facts: false tasks: - name: Create HTML summary report # 若控制节点是Windows系统,替换为ansible.windows.win_template template: src: report.j2 # 生成带时间戳的唯一文件名,避免覆盖旧报告 dest: "/server/reports/Windows_Patch_Report_{{ ansible_date_time.iso8601_basic_short }}.html"
方案二:使用run_once强制单任务执行
在原Playbook中给报告生成任务添加run_once: yes,可选搭配delegate_to: localhost确保任务在控制节点执行,避免依赖目标主机权限,实现方式更简洁。
修改后的Playbook代码
- name: Search for Windows Updates and generate consolidated report hosts: windows_hosts tasks: - name: Search for pending Windows Updates ansible.windows.win_updates: category_names: '*' server_selection: "windows_update" state: searched register: check_win_updates_patchresult - name: Create HTML summary report ansible.windows.win_template: src: report.j2 dest: "\\\\server\\reports\\Windows_Patch_Report_{{ ansible_date_time.iso8601_basic_short }}.html" # 强制任务仅执行一次 run_once: yes # 可选:指定在控制节点执行,替代在某台目标主机执行 delegate_to: localhost
适配汇总需求的Jinja模板(report.j2)
模板需要遍历所有目标主机的更新数据,同时处理数据缺失的异常情况,示例如下:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Windows更新汇总报告</title> <style> table { border-collapse: collapse; width: 90%; margin: 10px 0; } th, td { border: 1px solid #ddd; padding: 8px; text-align: left; } th { background-color: #f2f2f2; } .host-section { margin-bottom: 20px; } </style> </head> <body> <h1>Windows更新汇总报告 - {{ ansible_date_time.iso8601 }}</h1> {% for host in groups['windows_hosts'] %} <div class="host-section"> <h2>主机:{{ host }}</h2> {% if hostvars[host]['check_win_updates_patchresult'] is defined %} {% set updates = hostvars[host]['check_win_updates_patchresult'].updates %} {% if updates | length > 0 %} <table> <tr> <th>KB编号</th> <th>更新标题</th> <th>分类</th> <th>大小(MB)</th> </tr> {% for update in updates %} <tr> <td>{{ update.kb | join(', ') }}</td> <td>{{ update.title }}</td> <td>{{ update.category | join(', ') }}</td> <td>{{ (update.size / 1024 / 1024) | round(2) }}</td> </tr> {% endfor %} </table> {% else %} <p>无待安装更新</p> {% endif %} {% else %} <p>无法获取该主机的更新数据(可能执行失败)</p> {% endif %} </div> <hr> {% endfor %} </body> </html>
关键注意事项
- 模板路径:确保控制节点能访问
report.j2模板,通常将模板放在Role的templates目录下,或指定绝对路径。 - 权限问题:如果报告目标路径是共享目录,需确保执行Ansible的用户拥有读写权限。
- 控制节点系统适配:若控制节点是Windows,将
template模块替换为ansible.windows.win_template,路径使用Windows格式(如\\server\\reports\\...)。
内容的提问来源于stack exchange,提问作者OrionUK
相关产品推荐
相关产品推荐

