如何过滤Ansible的stdout_lines并生成指定格式的服务状态邮件
解决Ansible邮件输出Hyper-V服务状态格式问题
方案一:过滤现有stdout_lines文本内容
你的问题在于直接输出了原始命令行的文本列表,包含空白行、表头和分隔线,只需在Jinja2模板中添加过滤和格式化逻辑即可:
修改邮件任务的body部分,通过Jinja2过滤器筛选有效行,再拆分服务名与状态:
- name: Send e-mail run_once: true mail: host: test.example.com port: 1111 to: test@example.com subject: Check_Service_State subtype: html body: | {% for item in play_hosts %} <strong>{{ item }}:</strong><br> {% set service_lines = hostvars[item]['result']['stdout_lines'] | reject('equalto', '') | reject('search', '^-+$') | reject('search', '^DisplayName') %} {% for line in service_lines %} {% set service_name = line.rsplit(' ', 1)[0] %} {% set status = line.rsplit(' ', 1)[1] %} {{ service_name }}: {{ status }}<br> {% endfor %} <br> {% endfor %} from: test@example.com ignore_errors: yes delegate_to: localhost
关键过滤逻辑:
reject('equalto', ''):移除空白行reject('search', '^-+$'):移除表头下方的短横线分隔行reject('search', '^DisplayName'):移除表头行rsplit(' ', 1):从行尾拆分状态(避免服务名含空格导致拆分错误)
方案二:用JSON格式输出(更优雅可靠)
解析纯文本容易出现兼容性问题,推荐让PowerShell输出JSON结构化数据,Ansible直接解析使用:
第一步:修改win_shell任务输出JSON
- name: Get Hyper-V services (JSON format) win_shell: | Get-Service -DisplayName Hyper-V* | Select-Object DisplayName, Status | ConvertTo-Json register: result
第二步:邮件任务解析JSON并格式化
- name: Send e-mail run_once: true mail: host: test.example.com port: 1111 to: test@example.com subject: Check_Service_State subtype: html body: | {% for item in play_hosts %} <strong>{{ item }}:</strong><br> {% set services = hostvars[item]['result']['stdout'] | from_json %} {% for service in services %} {{ service.DisplayName }}: {{ service.Status }}<br> {% endfor %} <br> {% endfor %} from: test@example.com ignore_errors: yes delegate_to: localhost
优势:
- 彻底规避文本解析的潜在问题(如服务名含空格、状态值格式变化)
- 结构化数据更易维护,后续可轻松扩展字段或调整格式
内容的提问来源于stack exchange,提问作者Ivan
相关产品推荐
相关产品推荐

