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

Ansible 2.4.1.0邮件回调插件未输出预期失败消息求助

解决Ansible邮件回调未输出自定义失败消息的问题

我明白你遇到的困扰了——用with_items循环执行fail模块时,虽然任务执行日志里能看到自定义的失败消息,但邮件回调却只显示“All items completed”。这是因为Ansible的默认邮件回调插件会抓取任务级别的失败信息,而不是单个循环item的消息。当循环任务中有失败项时,任务整体的失败消息默认就是“All items completed”,你定义的msg属于单个item的结果,不会被默认回调捕获。

下面给你两种可行的解决办法:

方法一:调整任务结构,先收集违规端口再统一告警

这种方法不需要修改插件,通过拆分任务来确保自定义消息能被邮件回调正确捕获:

  1. 先收集所有违规端口到变量中:
- name: Collect rogue ports
  tags: ports
  set_fact:
    rogue_ports: "{{ rogue_ports | default([]) + [item] }}"
  with_items: "{{ ports_var.stdout_lines }}"
  when: item not in ports_lookup_var
  1. 检查是否存在违规端口,若存在则触发自定义告警:
- name: Trigger alert for rogue ports
  tags: ports
  fail:
    msg: "Ansible: Alert - Rogue Port {{ item }}"
  with_items: "{{ rogue_ports }}"
  when: rogue_ports | length > 0

如果希望邮件里一次性显示所有违规端口(而不是每条单独告警),可以把第二个任务改成:

- name: Trigger alert for rogue ports
  tags: ports
  fail:
    msg: "Ansible: Alert - Rogue Ports: {{ rogue_ports | join(', ') }}"
  when: rogue_ports | length > 0

这样修改后,邮件回调会抓取到fail任务的自定义msg,完全符合你的预期。

方法二:自定义邮件回调插件,捕获循环item的失败消息

如果你想保留原有的循环任务结构,可以自定义一个邮件回调插件,让它遍历循环任务的每个item结果,提取失败的自定义消息。

在你的Ansible项目目录下创建callback_plugins/custom_mail.py文件,内容如下:

from ansible.plugins.callback import CallbackBase
import smtplib
from email.mime.text import MIMEText

class CallbackModule(CallbackBase):
    CALLBACK_VERSION = 2.0
    CALLBACK_TYPE = 'notification'
    CALLBACK_NAME = 'custom_mail'
    CALLBACK_NEEDS_WHITELIST = True

    def __init__(self):
        super(CallbackModule, self).__init__()
        # 根据你的环境配置邮件参数
        self.smtp_server = 'localhost'
        self.smtp_port = 25
        self.from_addr = 'root@ansible.?????.local'
        self.to_addr = 'root@ansible.?????.local'

    def v2_runner_on_failed(self, result, ignore_errors=False):
        host = result._host.get_name()
        playbook = result._task._playbook.name
        task = result._task.name
        module = result._task.action

        # 处理循环任务的失败消息
        error_msg = ""
        if 'results' in result._result:
            error_lines = []
            for item_res in result._result['results']:
                if item_res.get('failed', False):
                    item = item_res.get('item', 'Unknown item')
                    msg = item_res.get('msg', 'No error message')
                    error_lines.append(f"- {msg}")
            error_msg = "\n".join(error_lines)
        else:
            error_msg = result._result.get('msg', 'Unknown error')

        # 构造邮件内容
        subject = f"Failed: {task} on {host}"
        email_body = f"""Playbook: {playbook}
Task: {task}
Module: {module}
Host: {host}
Failed items:
{error_msg}

Full error details: {result._result}"""

        # 发送邮件
        msg = MIMEText(email_body)
        msg['Subject'] = subject
        msg['From'] = self.from_addr
        msg['To'] = self.to_addr

        try:
            with smtplib.SMTP(self.smtp_server, self.smtp_port) as smtp:
                smtp.sendmail(self.from_addr, self.to_addr, msg.as_string())
        except Exception as e:
            self._display.warning(f"Failed to send alert email: {str(e)}")

然后修改ansible.cfg,启用这个自定义插件:

[defaults]
callback_plugins = ./callback_plugins
callback_whitelist = custom_mail

这样,当循环任务中有失败项时,邮件会自动收集所有失败item的自定义消息并发送。

内容的提问来源于stack exchange,提问作者Robert Gabriel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:19:39