
Отправка алертов Zabbix в Telegram
Zabbix — самая вменяемая система мониторинга всего, что возможно. Чтобы быстро реагировать на алерты электронная почта не очень подходит, да и почта не всегда может дойти. А телега для этого самое то.
Для отправки алертов в телегу долго использовал свой малюсенький скриптик на баше. Потом через какое-то время появилась встроенная поддержка в самом заббиксе, но по сути делает то же самое.
В некоторых случаях при алертах приходилось залезать в графану и смотреть на графики, чтобы лучше понять проблему. Мысль добавить графики приходила в голову, но как-то думал, что не особо то и нужно. Но оказалось, что многим нужна. Допилил скрипт для отправки еще и графиков + добавил всяких плюшек. Оказалось с графиками стало жить легче 🙂 Скрипт выложен на гитхабе. Дока там есть, но опишу все здесь попонятнее. Настройка будет идти на Debian 11 и Zabbix 6.0.
Установка и настройка скрипта
Для начала нужно установить зависимости:
apt install curl jo jq
Переходим в директорию с кастомными скриптами заббикса:
cd /usr/lib/zabbix/alertscripts
Качаем сам скрипт:
wget https://raw.githubusercontent.com/zevilz/zabbix-alertscript-telegram/main/telegram.sh
Сразу меняем права у скрипта, т.к. там будут важные данные, и делаем его исполняемым:
chmod 700 telegram.sh
chown zabbix:zabbix telegram.sh
Чтобы скрипт мог отправлять в телегу, нужен бот. Зарегистрировать его можно у другого известного официального бота @BotFather. Процесс регистрации описывать не буду, там все просто. Нам для скрипта нужен будет только токен нового бота. Он будет выдан после регистрации бота. Копируем его, открываем скрипт в любом любимом редакторе, вставляем в значение переменной TELEGRAM_BOT_TOKEN полученный токен, сохраняем и выходим.
По дефолту ошибки скрипта будут писаться в /usr/lib/zabbix/alertscripts/zbx_tlg_bot.log. Если лог нужно писать в другое место, то указываем этот путь в переменной SCRIPT_LOG_PATH. Файл лога создается автоматически, если его нет. Если юзер zabbix не сможет его создать, то получим ошибку при тесте отправки.
Не забываем перейти к чату с ботом и стартануть его. Если будете тестить в группе, то нужно добавить в нее бота и дать права на отправку сообщений.
Скрипт уже готов к отправке текстовых сообщений. Теперь нужно добавить новый способ оповещений в Zabbix. Для этого переходим Администрирование -> Способы оповещений и там вверху справа жмем на кнопку Создать способ оповещения.
В окрывшемся окне указываем следующее:
- Имя —
Telegram - Тип —
Скрипт - Имя скрипта —
telegram.sh
В параметры скрипта добавляем:
{ALERT.SENDTO}{ALERT.SUBJECT}{ALERT.MESSAGE}

Во вкладке Шаблоны сообщений добавляем нужные шаблоны. Сам текст шаблонов можно скопировать из существующих способов оповещений. Никакого дополнительного форматирования не нужно, просто текст. Дополнительно можно использовать Markdown и накидать смайликов 🙂 Далее тыкаем по кнопке Добавить.

Шаблоны сообщений также можно задавать непосредственно в действиях триггеров. У них будет больший приоритет, и можно задавать разные шаблоны для разных случаев.
Теперь можно тестить отправку алертов. Для этого тыкаем по Тест в строке с новым способом оповещения:

В открывшемся окошке указываем свой ID или ID группы телеги (его можно узнать у бота zGetMyID_bot) и жмем на кнопку Тест. Если все ок, то получим такое уведомление:

А в телегу от бота придет это тестовое сообщение:

А если отправка провалится, то вы где-то накосячили. В уведомлении увидим ошибку, а если ее нет, то смотрим в лог скрипта.
Отправка графиков
Для отправки графиков нам нужен юзер, который будет иметь доступ к API и к графикам нужных хостов в веб-интерфейсе. Скрипт авторизуется в API, получает данные о графике, который привязан к элементу данных в триггере. Если график есть, то авторизуется уже в веб-интерфейсе и дергает сам график. Для этого можно заюзать существующего супер-админа, он имеет доступ ко всему. Но теоретическим не очень безопасно, т.к. его данные для входа будут прописаны в скрипте, а они при определенных обстоятельствах могут утечь. Можно создать для этого обычного юзера с необходимыми правами, но нужно будет ему еще давать права на хосты и группы хостов, что неудобно. Проще всего создать юзера с новой супер-админской ролью, где будут минимальные права и доступ в API только к нужному методу (graph.get). Например, так:

С юзером определились. Теперь нужно определить необходимые переменные в скрипте:
GRAPHS— включение отправки графиков, тут ставим1;GRAPHS_DIR— полный путь к директории, куда временно будут сохранятся графики (по дефолту пусто, а графики будут сохраняться в директорию; директория для графиков создается автоматически, если её нет; если юзер/tmp/zbx_graphszabbixне сможет её создать, то получим ошибку при тесте отправки);ZABBIX_URL— полная ссылка к веб-интерфейсу заббикса (например:https://zabbix.site.com);ZABBIX_USER— юзер с доступами к графикам;ZABBIX_PASS— пароль юзера;ZABBIX_COOKIES_LIFETIME— время жизни куки авторизации в заббиксе (время жизни куки устанавливается на 14 дней, но они могут истечь раньше этого времени, а без авторизации не получится дергать графики; по дефолту стоит 30 секунд, т.е. переавторизация будет только при простое получения графиков более 30 сек; можно так и оставить);ZABBIX_COOKIES_PATH— полный путь к файлу куки (по дефолту пусто, а куки будут писаться в директорию скрипта в файл/usr/lib/zabbix/alertscripts/zbx_cookies; файл с куками создается автоматически, если его нет; если юзерzabbixне сможет его создать, то получим ошибку при тесте отправки).
Для отправки графиков необходимо добавить вот такую строчку в любое место текста сообщения в нужных шаблонах сообщений (обычно это только тип Проблема):
<graph:{ITEM.ID1}:1h:900:300>
Где:
{ITEM.ID1}— родной макрос, куда попадает ID первого итема из выражения триггера;1h— период, за который нужно получить график относительно текущего времени (может быть числом в секундах либо в относительных величинах:m— минуты,h— часы,d— дни,w— недели,M— месяцы,y— года);900— кастомная ширина графика;300— кастомная высота графика.
Ширина и высота необязательны. Если не указывать вообще или указать 0, то размеры будут те, которые указаны в настройках графика в веб-интерфейсе.
Для проверки отправки графиков необходимо вызвать срабатывание любого триггера, где для элемента данных создан график. К примеру, возьмем триггер перегруза CPU. Для этого нагрузим все ядра любого хоста, где активен этот триггер:
openssl speed -multi $(grep -ci processor /proc/cpuinfo)
Через какое-то время (в зависимости от порогов срабатывания триггера) получим алерт с графиком:

Также можно тестить отправку во встроенном тесте способа оповещени. Для этого добавим строку с данными графика в окошко теста ({ITEM.ID1} нужно будет сменить на реальный ID итема, его можно взять из адресной строки из истории или страницы настройки этого итема) и тыкнуть по кнопке Тест:

В результате получим тестовое сообщение с графиком:

Для временного отключения графиков не нужно удалять строку с данными графика из шаблона оповещений. Достаточно только установить значение переменной GRAPHS в 0. Эта строка удаляется из текста сообщения в любом случае.
Другие переменные скрипта
Во многих триггерах в описании триггера вывожу дополнительные данные и значения итемов в конце сообщения. Бывает полезно получать оперативные данные прямо в алерте. В некоторых шаблонах эти описания могут быть очень длинными (например, ошибки в логах веб-сервера), а у телеги есть ограничения по длине текста в обычных сообщениях (4096 символов) и подписям к изображениям (1024 символа).
Пробовал разбивать сообщения на несколько, но ломается markdown разметка, появляется мешанина из кучи сообщений (особенно если параллельно срабатывают несколько подобных триггеров), да и не особо бывает нужно видеть весь текст. В итоге просто сделал обрезку сообщений. Если сообщение длиньше установленных лимитов, то текст обрезается, а в конце добавляется многоточие.
Максимальная длина текстов задается в переменных скрипта:
TELEGRAM_MESSAGE_LIMIT— макисмальная длина текстовых сообщений (по дефолту4000);TELEGRAM_CAPTION_LIMIT— максимальная длина подписей к графикам (по дефолту900);
Для лучшего восприятия сообщений описание чаще всего в шаблонах запихиваю в блоки кода (тройной апостроф по краям):
Started: {EVENT.TIME} {EVENT.DATE}
Severity: {EVENT.SEVERITY}
Original problem ID: {EVENT.ID}
```
{TRIGGER.DESCRIPTION}```
Но при обрезке такого сообщения вместе с текстом обрежутся еще и закрывающие апострофы, а телега ругнется на такое сообщение и не отправит его. Для такого случая добавил переменную MONOSPACED_DESCRIPTION. Если она включена (значение 1), а очень длинное описание запихнуто в блок кода, то скрипт обрежет текст и корректно завершит блок кода.

