为所有主机发送一封电子邮件警报

为所有主机发送一封电子邮件警报

有人知道如何将所有输出合并到一封电子邮件警报中吗?我创建了一个剧本来检查只读文件系统,并在发现时发出警报。但问题是,如果 2 台服务器有问题,我会收到 2 封电子邮件警报。我需要针对所有有问题的主机发出单一警报。任何帮助都将不胜感激。:) 我尝试了很多方法,但我只收到针对单个主机的单一警报,它淹没了我的收件箱。

---

- hosts: free

remote_user: snail

gather_facts: false


tasks:

- name: run echo Command

shell: if grep "[[:space:]]ro[[:space:],]" /proc/mounts | grep -v tmpfs > /dev/null ; then echo 'read-only-FS';else echo 'all_good'; fi

register: outcome


- name: get the IP address

shell: hostname

register: host_name


- name: Send Mail Alert

local_action: mail

host="mailxxxx"

subject="[Read-Only FS] Testing Mail"

body="Read-Only FileSystem on {{ host_name.stdout }}"

to="[email protected]"

from="root"

when: outcome.stdout == "read-only-FS"

答案1

我能想到的最简单的方法是:

  1. 检查是否存在具有某些“随机”名称(如“/tmp/ansible-mail”)的文件。这应该是delegate_to=localhostrun_once=True。如果有文件,则应将其删除。(带有 的文件模块 state=absent
  2. 检查 FS 是否已更改 - 注册它。
  3. 如果 2 被改变则附加到此文件 - 因为多个主机可能想要附加serial=1可能是一个选项,delegate_to=localhost。
  4. 检查是否存在此“随机”文件 - 注册它。委托给本地主机并设置 run_once。
  5. 如果 4 为真。则运行邮件。再使用委托和 run_once。

如果有需要,我可以做简单的 POC。

编辑:

---
- hosts: tmp1, tmp2
  # user, become etc should normaly be set in ansible.cfg
  user: ansible
  become: true
  vars:
    mail_body_file: "/tmp/ansible-mailing-tmp123" 
  tasks:
    - name: Check if there is {{mail_body_file}}
      file:
        state: absent
        path: "{{mail_body_file}}"
      delegate_to: localhost
      run_once: true
      become: false

    - name: Task looking for change, command always reports change so I used it for testing
      command: "echo 123"  
      register: my_test

    - name: Create {{mail_body_file}}
      file:
        state: touch
        path: "{{mail_body_file}}"
      delegate_to: localhost
      run_once: true
      become: false
    # Use shell because lineinfile has race condition
    # with echo >> we put race condition problem on filesystem
    - name: add line about change on host
      shell: "echo {{inventory_hostname}} has change >> {{mail_body_file}}"
      delegate_to: localhost
      when: my_test.changed
      become: false

    - name: get the mail body to variable
      register: mail_body
      command: "cat {{mail_body_file}}"
      delegate_to: localhost
      run_once: True

    - name: mail about change
      mail:
        body: "{{mail_body.stdout}}"
        to: "[email protected]"
        from: "root"
        subject: "Test"
      delegate_to: localhost
      run_once: True

请注意你应该测试一下

答案2

这样的剧本可能会奏效。

我们在剧本中有两个单独的剧本,在第一个剧本中,我们连接到远程主机并收集结果。在第二个剧本中,我们在本地主机上运行并发送邮件。使用内联 jinja 模板,它将循环遍历与 中定义的主机模式匹配的所有主机hosts_pattern

---
- name: gather data
  hosts: linux_systems
  gather_facts: false
  tasks:

  - name: Command to check systems for ead only mounts
    shell: >
      if grep "[[:space:]]ro[[:space:],]" /proc/mounts |
        grep -v tmpfs > /dev/null ; then
      echo 'read-only-FS';else echo 'all_good'; fi
    register: read_only_check

  - name: Get the output of `hostname`
    command: hostname
    register: host_name

- name: email report
  hosts: localhost
  gather_facts: false
  vars:
    hosts_pattern: linux_systems
  tasks:

  - name: Email report of systems with read only filesystems
    mail:
      host: some-smtp.server.example.com
      port: 25
      to: John Smith <[email protected]>
      subject: "[Read-Only FS] Testing Mail"
      body: |
        Report from playbook check_readonly_filesystems.

        {% for host_item in lookup('inventory_hostnames', hosts_pattern, wantlist=True) %}
        {% if hostvars[host_item]['read_only_check'] is defined and
              hostvars[host_item]['read_only_check'].stdout is defined and
              hostvars[host_item]['read_only_check'].stdout == "read-only-FS" %}
        Read only - {{ hostvars[host_item]['inventory_hostname'] }} aka {{ hostvars[host_item]['host_name'].stdout }}
        {% else %}
        Good host - {{ hostvars[host_item]['inventory_hostname'] }} aka {{ hostvars[host_item]['host_name'].stdout }}
        {% endif %}
        {% endfor %}

相关内容