Перейти к основному содержанию

Zabbix — оповещение по телефону через Asterisk

Zabbix

Как-то раз мы проспали проблему. Zabbix прислал пару SMS, но никто ночью не проснулся. А если бы zabbix позвонил, да ещё бы и рассказал о проблеме, то было бы проще всё упавшее поднимать. Учим zabbix звонить на телефон.

Как показывает практика, звонки через свою АТС могут быть дешевле, чем отправка SMS.

Что у нас есть:

  • Zabbix сервер версии 3.4.15. Впрочем, версия не особо важна. Операционная система Ubuntu.
  • Asterisk сервер.

Прежде чем приступить к реализации функционала я нашёл в сети Интернет с десяток статей. Где-то содрал куски кода и переписал их по-своему, где-то взял за основу теорию или практику. В итоге получилось что-то своё, со своими плюсами и минусами.

Теория

  1. При возникновении проблемы zabbix сервер должен выполнить bash скрипт, который нам и выполнит всю работу по совершению звонка. Весь необходимый функционал в zabbix уже есть, нам нужно только написать скрипт и всё настроить.
  2. Bash скрипт генерирует из текста ошибки звуковой WAV файл и CALL файл для Asterisk.
  3. Bash скрипт загружает по SCP на сервер Asterisk сгенерированные файлы, устанавливает им нужные права, помещает в нужные директории.
  4. Asterisk совершает звонок и проигрывает сообщение.

Дополнительные условия:

  • Bash скрипт должен чистить за собой старые WAV файлы. Call файлы Asterisk почистит сам.
  • Bash скрипт не должен звонить слишком часто при массовом сбое. Основная задача — разбудить админов, а не отправить максимальное количество звонков.
  • Должны быть логи звонков.
  • Должна быть поддержка русского языка.
  • Должна быть возможность тонкой настройки для каждого пользователя, о каких триггерах уведомлять по телефону.

Подготовка серверов

WAV файл будем создавать на zabbix сервере, пример:

Создать WAV файл из текста в Ubuntu

Устанавливаем на zabbix сервере библиотеки:

apt-get install festival festvox-ru uuid
  • festival — библиотека для генерации звукового файла из текста.
  • festvox-ru — поддержка русского языка для festival.
  • uuid — в bash скрипте я использую uuid для генерации уникального имени файла.

В скрипте я буду копировать WAV и CALL файлы на asterisk по SCP. Нужно настроить беспарольный вход по SSH от пользователя zabbix на zabbix сервере пользователю root на asterisk сервере. Вынес подробности в статью:

SCP — копируем файл без пароля

А если коротко, то на zabbix сервере под рутом:

ssh-keygen

На все вопросы жмём ввод, получаем пару ключей. Копируем публичный ключ на asterisk сервер (он у меня называется freepbx):

scp ~/.ssh/id_rsa.pub root@freepbx:~/.ssh/authorized_keys

Папку .ssh с ключами переношу в домашнюю директорию пользователя zabbix на zabbix сервере, потому что bash скрипт будет выполняться от его имени, и SCP тоже.

Bash скрипт

В настройках zabbix сервера /etc/zabbix/zabbix_server.conf смотрим что написано в параметре AlertScriptsPath:

AlertScriptsPath=/usr/lib/zabbix/alertscripts

Раскомментируйте параметр при необходимости.

У меня скрипт для уведомлений находятся по умолчанию в директории /usr/lib/zabbix/alertscripts. Создаю в ней пустой файл для логов /usr/lib/zabbix/alertscripts/freepbxgate.log, пользователь zabbix должен иметь права на чтение и запись. B создаю bash скрипт /usr/lib/zabbix/alertscripts/freepbxgate.sh. Пользователь zabbix должен иметь права на чтение и выполнение. Содержимое скрипта:

#!/bin/bash
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
# -----------------------------------
# настройки
# local zabbix server
workdir="/tmp"
logfile="/usr/lib/zabbix/alertscripts/freepbxgate.log"
prefix="zabbix1"
prefixname="Сообщ+ение от монит+оринга."
# remote asterisk сервер
aserver="root@freepbx.domain.local"
adir="/tmp"
asounds="/var/lib/asterisk/sounds/"
aout="/var/spool/asterisk/outgoing/"
# -----------------------------------
to=$1
subject=$2
phone=`echo $to | awk -F"/" '{ print $1}'`
tags=`echo $to | awk -F"/" '{ print $2}'`
#чистим subject
txt2wav=$(echo "$subject" | sed -r 's/[\.,\!\?]/ /g' | sed 's/(\([^)]*\))//g' | sed 's/[^0-9a-zA-Zа-яА-ЯёЁ ]//g' | tr -s " " | sed 's/^[ \t]*//;s/[ \t]*$//')
# функция генерации и отправки файлов на asterisk
callme(){
   px=$1
   #уникальное имя для wav и call файлов
   uid=`uuid`
   fp="${prefix}_${uid}_${phone}"
   #генерация wav
   wavfile="${workdir}/${fp}.wav"
   command1="echo $prefixname $px $txt2wav | /usr/bin/text2wave -F 8000 -eval '(voice_msu_ru_nsh_clunits)' 2>/dev/null > ${wavfile}"
   echo $command1 | /bin/bash
   #генерация call
   callfile="${workdir}/${fp}.call"
   touch $callfile
   echo "Channel: Local/$phone@from-internal" > $callfile
   echo "MaxRetries: 3" >> $callfile
   echo "RetryTime: 60" >> $callfile
   echo "WaitTime: 60" >> $callfile
   echo "Callerid: Wake Up Calls <*68>" >> $callfile
   echo "Application: Playback" >> $callfile
   echo "Data: $fp" >> $callfile
   #Перенос файлов на asterisk
   scp $wavfile $aserver:$adir
   scp $callfile $aserver:$adir
   rm $wavfile
   rm $callfile
   ssh $aserver "chown asterisk\: ${adir}/${fp}* && chmod 777 ${adir}/${fp}.wav && mv ${adir}/${fp}.wav ${asounds} && mv ${adir}/${fp}.call ${aout} && find ${asounds} -name '${prefix}*' -type f -mmin +10 -delete"
}
while IFS=',' read -ra item; do
   for i in "${item[@]}"; do
       if grep -q "$i" <<<$subject; then
           date_now1=`date | awk -F":" '{print $1":"$2}'`
           date_now2=`date | awk '{print $5,$6}'`
           msg_count=`tail -n 5000 ${logfile} | grep "${date_now1}" | grep "${date_now2}" | grep "${phone}" | wc -l`
           date_now=`date`
           if [ $msg_count -gt 0 ]; then
               if [ $msg_count -eq 1 ]; then
                   callme "+Очень мн+ого сообщ+ений, ч+асть звонк+ов проп+ущена!"
                   echo "$date_now $to $txt2wav" >> ${logfile}
               else
                   echo "$date_now $to $txt2wav | не отправлено" >> ${logfile}
               fi
           else
               callme
               echo "$date_now $to $txt2wav" >> ${logfile}
           fi
       fi
   done
done <<< "$tags"

На вход принимается два параметра:

  • Получатель в формате "79990001122/(TAG1),(TAG2),(TAG3)"
  • Заголовок триггера, например, "Всё сломалось! (TAG2) Срочно просыпайтесь!"

Получатель состоит из номера мобильного телефона и списка тегов через запятую, тегов может быть много. Тег — это кусок текста из заголовка триггера. Я, например, вставляю в названия триггеров теги вида (WIN) или (LINUX) или (SMS).

Заголовок — это название триггера.

Если у получателя есть тег, который присутствует в тексте заголовка, то получателю будет отправлен звонок на телефон. Если у получателя нет такого тега или тегов, то звонка не будет.

Параметры bash скрипта:

  • workdir="/tmp" — директория на zabbix сервере, в которой будут генерироваться WAV и CALL файлы.
  • logfile="/usr/lib/zabbix/alertscripts/freepbxgate.log" — лог файл на zabbix сервере.
  • prefix="zabbix1" — префикс в названиях файлов. У меня несколько zabbix серверов, для каждого будет уникальный префикс.
  • prefixname="Сообщ+ение от монит+оринга." — с этого текста начинается каждый звонок. Плюсы указывают на ударение в слове.
  • aserver="root@freepbx.domain.local" — логин и имя сервера asterisk для передачи файлов SCP.
  • adir="/tmp" — директория на asterisk сервере, в которую первоначально копируются файлы. В ней им настраиваются права и владелец.
  • asounds="/var/lib/asterisk/sounds/" — директория на asterisk сервере, в которую копируются WAW файлы.
  • aout="/var/spool/asterisk/outgoing/" — директория на asterisk сервере, в которую копируются CALL файлы.

Если за минуту поступит второй звонок, то в текст добавится "+Очень мн+ого сообщ+ений, ч+асть звонк+ов проп+ущена!", больше в эту минуту звонков не будет, хотя логи продолжат записываться. Думаю, потом я сделаю период звонков побольше.

Параметры CALL файла измените для своих нужд. Например, у меня в качестве Callerid используется существующий Wake Up Calls <*68>, который есть в freepbx для звонков будильника. Если сообщение нужно проиграть три раза, то замените строчку:

echo "Data: $fp" >> $callfile

на

echo "Data: $fp&$fp&$fp" >> $callfile

Настройка zabbix

Administration > Media types. Добавляем новый тип FreePBX Gate.

zabbix

Настраиваем:

  • Name: FreePBX Gate
  • Type: Script

zabbix

Configuration > Actions. Создаём Report problems to Zabbix administrators (FREEPBX).

zabbix

Action — указываем нужные нам условия.

zabbix

Operations. Здесь можно настроить Subject, именно он будет читаться в телефоне.

zabbix

Добавляем операцию Send message to user groups: Zabbix administrators via FreePBX Gate.

zabbix

Здесь нужно указать, что уведомление отправляем через FreePBX Gate.

В Recovery operations можно тоже добавить звонок о том, что проблема устранена, но я убрал эту возможность.

zabbix

Acknowledgement operations мне тоже не нужно.

zabbix

Теперь у себя в настройках смотрю раздел Media и добавляю FreePBX Gate 79990001122/(SMS AGENT),(PING),(SMS),(WEB),(VR),(HW),(1C),(WIN),(CRM) 1-7,00:00-24:00 NIWAHD, потом перенастрою на ночь.

zabbix

Вот пример триггеров, на которые должен отреагировать скрипт:

zabbix

Текст "(SMS AGENT)" есть в списке моих тегов, поэтому звонок пройдёт.

Теги

 

Похожие материалы

Zabbix шаблон для мониторинга сервера HP Proliant DL360 Gen9

Делюсь полезным шаблоном для мониторинга сервера  HP Proliant DL360 Gen9. Мониторим по IPMI. Шаблон делал сам. Версия 3. Обновление шаблона от 19.03.2019. Исправлены данные по электропитанию, добавлены триггеры, внесены IPMI value mapping, добавлены графики, приложения. В шаблоне 7 приложений, 80 элементов данных, 39 триггеров и 3 графика.

Теги

Zabbix шаблон для мониторинга RAID контроллеров LSI, 4-я версия

Сижу я вечером дома после работы, вдруг, понимаю как вытащить данные о температуре и ошибках физических дисков контроллеров LSI.

Zabbix, ProLiant и тормоза IPMI

Я раньше сталкивался с проблемой мониторинга серверов HP ProLiant девятого поколения по SNMP, ссылку добавлю ниже. В тот раз я вышел из тупика переходом на мониторинг северов по IPMI. Со временем девятое поколение серверов стало плавно меняться на десятое, при этом мониторинг так и остался на IPMI, я просто для каждой новой модели сервера делал новый шаблон. И вот натыкаюсь на странный баг с IPMI.

Теги