当 ansible 中的主机无法通过 SSH 访问时,我希望收到一封电子邮件。
我试图写一本剧本来做到这一点(见下文)。收集事实后,任何无法访问的主机都会被丢弃,因此我的发送电子邮件的任务永远不会为无法访问的主机执行。
-name:检查主机可访问性 主办方:全部 任务: - local_action: shell ssh deploy@{{ansible_hostname}} echo OK 注册:check_ssh - local_action:调试消息=“{{check_ssh.stdout}}” 当:check_ssh.stdout!=“确定”
多谢。
答案1
这是我的解决方案ansible > 2.0
:
- name: Check host accessibility
hosts: all
user: deploy
gather_facts: no
tasks:
- block:
- command: echo OK
- assert:
that:
- ansible_play_hosts == ansible_play_hosts_all
rescue:
- name: send email when something goes wrong (pe, cannot reach a machine)
local_action:
module: mail
host: localhost
to: < email here >
from: < email here >
subject: 'Host check - {{ (ansible_play_hosts_all | difference(ansible_play_hosts)) | first }}'
body: 'Cannot login into the machine'
when: inventory_hostname == "< hostname of main server here >"
这是迄今为止我能够提供的最佳解决方案。遗憾的是,它ansible
不认为unreachable
主机是failed
,所以rescue
永远不会调用一个部分。我已经解决了计算执行最后一个任务的主机数量与主机总数的问题。如果不同,则意味着至少有一台主机unreachable
,因此执行断言并转到该rescue
部分。然后,第二个问题是断言适用于所有主机,因此我们必须只选择一台主机来发送电子邮件(在本例中我选择了安装了ansible的服务器)。
答案2
我发现使用 Python 脚本是最简单的解决方案(比回调插件更容易,至少在我的 ansible 版本 1.7 上):
#!/usr/bin/env python
from __future__ import print_function
import ansible.inventory
import ansible.runner
from subprocess import Popen, PIPE
import sys
TO = "root"
def message(subject, body):
p = Popen(["mail", "-s", subject, TO], stdin=PIPE)
p.communicate(input=body)
res = p.wait()
if res != 0:
print("Failed to send message", file=sys.stderr)
def main():
im = ansible.inventory.Inventory()
runner = ansible.runner.Runner(
module_name='command',
module_args='sh -c "echo OK"',
sudo=True,
)
run = runner.run()
nosudo = set(run["dark"].keys())
runner = ansible.runner.Runner(
module_name='command',
module_args='sh -c "echo OK"',
sudo=False,
inventory=ansible.inventory.Inventory(list(nosudo)),
)
run = runner.run()
nonet = set(run["dark"].keys())
nosudo = nosudo - nonet
for host in nosudo:
message("Host check: %s" % host,
"Cannot execute 'sudo -u root ...' as user 'deploy'.")
for host in nonet:
message("Host check: %s" % host,
"Cannot login into the machine.")
if __name__ == '__main__':
main()