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

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 шаблон для мониторинга СХД — IBM Storwize V3700 или V7000

Делюсь полезными шаблонами для мониторинга СХД IBM Storwize V3700 или V7000. В шаблоне 430 элементов данных с триггерами. Работает на основе получаемых от СХД SNMP traps.

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

Делюсь полезным шаблоном для мониторинга сервера  HPE Proliant DL360 Gen10. Мониторим по IPMI. Шаблон делал сам. В шаблоне 8 приложений, 112 элементов данных, 49 триггеров и 4 графика.

Теги