Ansible

Ansible:在無法訪問的主機上發送電子郵件

  • January 9, 2019

每當無法通過 SSH 訪問 ansible 中的主機之一時,我想收到一封電子郵件。

我試圖寫一本劇本來做到這一點(見下文)。收集事實後,任何無法訪問的主機都會被丟棄,因此我發送電子郵件的任務永遠不會為無法訪問的主機執行。

-name:檢查主機可訪問性
主持人:全部
任務:
- local_action: shell ssh deploy@{{ansible_hostname}} echo OK
註冊:check_ssh
- local_action: debug msg="{{check_ssh.stdout}}"
何時: check_ssh.stdout != "OK"

非常感謝。

我發現使用 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()      

這是我的解決方案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沒有將unreachablehosts 視為是failed,因此rescue從未呼叫過一個部分。我已經克服了計算執行最後一個任務的主機數量與主機總數的問題。如果它不同,則意味著至少有一個主機是unreachable,因此執行斷言並轉到該rescue部分。然後,第二個問題是斷言適用於所有主機,所以我們只需要選擇一個主機來發送電子郵件(在這種情況下,我選擇了安裝 ansible 的伺服器)。

引用自:https://unix.stackexchange.com/questions/241880