Настройка уведомлений в Munin

    В статье Munin — мониторинг сети это просто! говорилось о том, что мониторинг нужен и что автор использует Munin, а так же описывалось как написать свой плагин. В этой статье мы рассмотрим как настроить Munin для отсылки уведомлений о проблемах на почтовый ящик.

    Для этого в файле /etc/munin/munin.conf нужно создать контакт и определить параметры\директивы для этого контакта. Делается это так:

    contacts someuser
    contact.someuser.command mail -s "Munin notification" somejuser@fnord.comm
    contact.someuser.always_send warning critical


    Данная конструкция означает, что мы создаём контакт someuser, отпределяем для него команду отправки уведомлений (в данном случае это команда mail) и какие уведомления отправлять (warning\предупреждения и critical\критические).

    Т.к. Munin собирает информацию каждые 5 минут, то уведомления (например закончилось место на диске, плагин df_) будут отсылаться раз в 5 минут. Теоретически, есть директива contact.contact.max_messages number, которая, как я понял, должна задавать максимальное число уведомлений для «warning/critical» события. Посмотреть список директив можно здесь
    У меня эта фича не заработала, поэтому пришлось писать свой скрипт, который бы разруливал эту ситуацию.

    Так же, директива contact.someuser.command позволяет использовать специальные переменные, вместо которых при отправке сообщения будут подставляться реальные значения. Список переменных тут.

    Разберём всё это на примере. Требуется: отсылать уведомления двум пользователям. Первый пользователь должен получать как критические, так и предупредительные сообщения. Второй только критические.

    Открываем /etc/munin/munin.conf и создаём контакты:

    contacts user1 user2
    contact.user1.command mail_send_mutt user1mail@gmail.com "Munin notification ${var:host}" "[${var:group};${var:host}] -> ${var:graph_title}: warnings: ${loop<,>:wfields ${var:label}=${var:value}}; criticals: ${loop<,>:cfields ${var:label}=${var:value}}"
    contact.user1.always_send warning critical

    contact.user2.command mail_send_mutt user2mail@yandex.ru "Munin notification ${var:host}" "[${var:group};${var:host}] -> ${var:graph_title}: warnings: ${loop<,>:wfields ${var:label}=${var:value}}; criticals: ${loop<,>:cfields ${var:label}=${var:value}}"
    contact.user2.always_send critical


    Здесь я использовал самописный скрипт mail_send_mutt, который принимает 3 входных параметра:
    1. E-mail пользователя
    2. Заголовок сообщения
    3. Текст сообщения

    Для отправки писем используется консольный почтовый клиент mutt, т.к. работает он быстро, надёжно и никаких дополнительных настроек не требует.

    Текст скрипта:
    #!/bin/bash
    # Отправка почтового сообщения через mutt
    # Принимаемые параметры:
    # 1. адрес для отправки
    # 2. тема письма
    # 3. текст письма

    # Для каждого электронного адреса создаётся свой лог-файл, в который записываются
    # все отправленные на этот адрес сообщения с датой и временем отправки.
    # Это нужно для того, что в дальнейшем можно было посмотреть что мы уже отправляли и
    # избавить админа от чтения кучи дубликатов. Также это может быть полезно при "разборе полётов"

    email=$1
    theme="$2"
    ptext="\"$3\""

    # Тип вывода сообщений: 0 - никуда не выводить, 1 - стандатрый вывод, 2 - в файл.
    type_out=0
    # Функция вывода.
    function out_text () {
    dbg_logfile="/var/log/munin/send_mess.log"
    if ! test -e "$dbg_logfile"
    then
    cat "" > "$dbg_logfile"
    fi

    case $type_out in
    1) echo "$1" ;;
    2) echo "$1" >> $dbg_logfile ;;
    *)
    esac
    }

    # Путь к логам
    var_path="/var/log/munin"
    # файл лога. имя файла создаётся на основе $email
    logfile=""
    # Если папки нет, то создадим
    if ! test -e "$var_path"
    then
    mkdir -p $var_path
    fi

    # Проверим указан для почтовый адрес
    if test -z $email
    then
    out_text "Нет адреса для отправки!"
    exit
    fi

    if test -z "$theme"
    then
    theme="null"
    fi

    if test -z "$ptext"
    then
    ptext="null"
    fi

    # Определим имя лог-файла по $email
    #logfile=${email/@/_}
    logfile=$var_path"/"${email/@/_}
    # Проверим, существует ли файл. Если нет - создадим
    if ! test -e "$logfile"
    then
    cat "" > "$logfile"
    fi

    # Счётчик сообщений, показывающий что было найдено сообщение с таким же тестом
    # как для текущей отправки и за сегодняшнюю дату
    str_found=0
    # Номер позиции разделителя. Используем для разбивки собщения на части
    dpos=0
    # Переменные, содержащие части сообщения из файла
    tdate=""
    tmail=""
    ttext=""
    # Разделитель строки из файла
    FS="|"
    # Разделитель для отсечения времени от даты
    FS_d='.'
    # Сегодняшняя дата
    curr_date=$(date +%Y-%m-%d)
    out_text "Current date: \"$curr_date\""

    # Проверим, отправляли ли мы уже такое сообщение
    while read fstr
    do
    # Разобьём строку на 3 части: дата, e-mail, сообщение
    # В качестве разделителя используется символ "|"
    out_text "str_found begin: $str_found"
    out_text "Find symbol: "$FS "; STR:" "$fstr"
    dpos=`expr index "$fstr" $FS`
    out_text "dpos: $dpos"
    tdate=`expr substr "$fstr" 1 $dpos`
    fstr=${fstr/$tdate/}
    tdate=${tdate/$FS/}
    out_text "NEW STR:" "$fstr"
    dpos=`expr index "$fstr" $FS`
    tmail=`expr substr "$fstr" 1 $dpos`
    ttext=${fstr/$tmail/}
    tmail=${tmail/$FS/}

    dpos=`expr index "$tdate" $FS_d`
    let "dpos-=1"
    tdate=`expr substr "$tdate" 1 $dpos`

    out_text "date: \"$tdate\""
    out_text "email: $tmail"
    out_text "ttext: $ttext"
    out_text "ptext: $ptext"
    out_text "------------------------------------------------------"
    # Если сообщение отправляли,
    if [ "$ptext" == "$ttext" ]
    then
    #то проверить когда оно было отправлено
    # если сегодня, то не нужно отправлять его повторно. (Увеличиваем счётчик найденных совпадений)
    out_text "Text EQ found!"
    if [ "$tdate" == "$curr_date" ]
    then
    out_text "Date EQ found!"
    let "str_found+=1"
    fi
    fi
    out_text "str_found end: $str_found"
    out_text "------------------------------------------------------"

    done < "$logfile" #используя перенаправление ввода считаем все строки из файла в цикле
    out_text "str_found: $str_found"
    if [ 0 -lt "$str_found" ]
    then
    out_text "Такое сообщение сегодня уже отправлялось!"
    exit
    fi

    # Отправим письмо
    echo "$ptext" | mutt $email -s "$theme"

    # Запишем в лог строку, которую мы отправили, чтобы в следующий раз такое сообщение не отправлять
    echo "$(date +%Y-%m-%d.%H-%M)|$email|$ptext" >> $logfile


    Я оставил в скрипте все свои комментарии, а так же вывод отладочной информации. Может кому сгодится. По-умолчанию вывод сообщений отключён. Если у кого-то есть идеи как улучшить скрипт, буду рад поправкам.
    К примеру есть такая конструкция:
    while IFS=: read name passwd uid gid fullname ignore
    do
    echo "$name ($fullname)"
    done </etc/passwd # перенаправление ввода.


    и цикл чтения файла лога для просмотра уже отправленных сообщений вроде как можно переделать следующим образом:
    while FS=| read tdate tmail ttext
    do
    .....
    done < "$logfile"

    но почему-то не работает так как описывается :(

    Комментарии 4

      0
      Спасибо за статью. Скажите, какие преимущества есть у Munin по сравнению с Nagios?
        0
        Пишут что nagios более навороченная система, но там нет графиков как в munin. Сам я nagios не ставил, поэтому не могу сказать о преимуществах\недостатках этой системы.
          0
          Munin и Nagios это системы немного разных задач.
          Основная задача Munin — собирать данные с серверов и рисовать по ним красивые графики.
          Nagios же заточен на мониторинг и выявление проблем и рассылку оповещений о них.

          Кстати графики у Nagios`а есть, через NagiosGrapher или Centreon
            0
            Да, спасибо, я уже знаю, всё-таки 1.5 года прошло, освоил и то и это и ещё много чего :-)

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое