Pull to refresh

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

Reading time5 min
Views2.8K
В статье 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"

но почему-то не работает так как описывается :(
Tags:
Hubs:
Total votes 3: ↑3 and ↓0+3
Comments4

Articles