有人知道如何将所有输出合并到一封电子邮件警报中吗?我创建了一个剧本来检查只读文件系统,并在发现时发出警报。但问题是,如果 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
我能想到的最简单的方法是:
- 检查是否存在具有某些“随机”名称(如“/tmp/ansible-mail”)的文件。这应该是
delegate_to=localhost
和run_once=True
。如果有文件,则应将其删除。(带有 的文件模块state=absent
) - 检查 FS 是否已更改 - 注册它。
- 如果 2 被改变则附加到此文件 - 因为多个主机可能想要附加
serial=1
可能是一个选项,delegate_to=localhost。 - 检查是否存在此“随机”文件 - 注册它。委托给本地主机并设置 run_once。
- 如果 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 %}