alibek Posted September 22, 2022 · Report post Есть Zabbix 5.4.2, в котором настроено оповещение в Телеграм. Для оповещалки используется штатный js-скрипт. Неудобством является то, что из оповещений Телеграма сложно понять, какие аварии все еще активны. Хочу сделать так, чтобы все активные аварии автоматически прикреплялись, а при закрытии аварии откреплялись. С закреплением проблем нет, в js-скрипте я после строчки response = request.post(url, data); добавлю еще вызов метода pinChatMessage и передам в нем response.message_id. Но вот как потом откреплять — пока не придумал. По идее, при возникновении аварии мне нужно где-то запоминать EVENT.ID и сопоставленный с ним идентификатор сообщения Телеграма. А при закрытии аварии нужно по EVENT.ID находить идентификатор ранее отправленного сообщения Телеграм. Но вот где хранить сопоставленный идентифиватор сообщения Телеграм — хороших идей нет. Лучше всего было бы хранить прямо в самом событии Заббикса (EVENT), но из js-скрипта к нему доступа нет. А изобретать костыли бы не хотелось. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Ser Posted September 22, 2022 · Report post А мне бы для монтажников нужно в чате телеграмм писать только Recent Alarm. Если данный список изменился, то удалять все записи в чате и писать новый обновленный список аварий. Есть идеи как это можно реализовать? Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
alibek Posted September 22, 2022 · Report post Запоминать при публикации message_id. При изменениях в составе аварий редактировать сообщение. Если аварий нет, то удалять сообщение и забывать message_id. Но это все будет каким-то сторонним решением. А я бы хотел без костылей, использовать штатный механизм заббикса. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
alibek Posted September 22, 2022 · Report post Хотя я тут немного покопался, можно по быстрому и почти штатно. Нужно добавить способ оповещения с типом "скрипт", в параметрах скрипта прописать {EVENT.ID}, настроить скрипт на возникновение проблемы и восстановление проблемы. Затем в /usr/lib/zabbix/alertscripts создать скрипт с указанным именем. Заббикс будет вызывать скрипт, передавая в него идентификатор события. Но в принципе, идентификатор события особо не нужен. Скрипт с помощью метода problem.get будет получать список текущих проблем, формировать текст и с помощью editMessageText обновлять текст сообщения. А идентификатор сообщения можно просто прописать прямо в скрипте. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
alibek Posted September 23, 2022 · Report post А вот и скрипт. <?php print "Подключение к NMS Zabbix\n"; if (!$zb = new Zabbix (null)) { print "! Сбой инициализации NMS Zabbix\n"; exit; } elseif ($zb->error()) { print "! Сбой подключения NMS Zabbix: " . $zb->error() . "\n"; exit; } file_put_contents("/tmp/{$script}_buffer.tmp", getmypid() . "\n", FILE_APPEND); print "Запрос действующих проблем из Zabbix...\n"; $tmp = $zb->request("problem.get", ["output"=>"extend", "recent"=>false, "severities"=>[4,5], "groupids"=>[19,20,21,22], "sortfield"=>["eventid"], "sortorder"=>"DESC"]); if (!$tmp) { print "! Ошибка получения списка проблем из Zabbix\n"; exit; } if (isset($tmp['error'])) { print "! Ошибка получения списка проблем из Zabbix: {$response['error']}\n"; exit; } $tmp = $tmp['result']; print "Запрос списка проблем из Zabbix выполнен, строк: " . count($tmp) . "\n"; $lst = []; foreach ($tmp as $rec) $lst[$rec['eventid']] = ['id'=>$rec['eventid'], 'clock'=>$rec['clock'], 'problem'=>$rec['name'], 'level'=>$rec['severity']]; print "Запрос деталей проблем из Zabbix...\n"; $tmp = $zb->request("event.get", ["output"=>"extend", "eventids"=>array_keys($lst), "selectHosts"=>"extend"]); if (!$tmp) { print "! Ошибка получения деталей проблем из Zabbix\n"; exit; } if (isset($tmp['error'])) { print "! Ошибка получения деталей проблем из Zabbix: {$response['error']}\n"; exit; } $tmp = $tmp['result']; foreach ($tmp as $rec) { if (!isset($lst[$rec['eventid']])) continue; if (!$rec['value']) continue; if (isset($rec['hosts'], $rec['hosts'][0])) { if ($rec['hosts'][0]['status']) continue; $lst[$rec['eventid']]['host'] = $rec['hosts'][0]['host']; $lst[$rec['eventid']]['title'] = $rec['hosts'][0]['name']; $lst[$rec['eventid']]['date'] = date("Y-m-d H:i", $rec['clock']); $lst[$rec['eventid']]['time'] = time() - $rec['clock']; } } $lst = array_filter($lst, function($rec) { return isset($rec['host']);}); $ids = array_keys($lst); sort($ids); $ids = implode(",", $ids); $ref = null; $old = ""; if (file_exists("/tmp/{$script}_telegram.tmp")) { $tmp = file_get_contents("/tmp/{$script}_telegram.tmp"); if (($tmp !== false) && $tmp) { $ref = trim(strtok($tmp, ":")); $old = trim(strtok(":")); } } print "Буфферизация отправки команд..."; sleep(2); if (!file_exists("/tmp/{$script}_buffer.tmp")) exit; $tmp = file_get_contents("/tmp/{$script}_buffer.tmp"); if (!$tmp) exit; $tmp = explode("\n", trim($tmp)); $tmp = end($tmp); if ($tmp != getmypid()) exit; unlink("/tmp/{$script}_buffer.tmp"); $tlg = new Telegram(); $rcpt = '...'; if ($ids) { print "# Есть аварии\n"; if ($ids == $old) { print "# Состав аварий не изменился, ничего не делать\n"; null; } else { print "# Состав аварий изменился\n"; $tlg->build(); $tlg->build("Список действующих аварий:\n"); foreach ($lst as $rec) { $tlg->build("- {$rec['title']} (с " . date("Y-m-d H:i", $rec['clock']) . ")\n"); } $tlg->build("\nИнформация обновлена: " . date("Y-m-d H:i:s")); if ($ref) { print "# Если есть закрепленное сообщение, то обновить его\n"; $tlg->editMessageText($rcpt, $ref); file_put_contents("/tmp/{$script}_telegram.tmp", "{$ref}: {$ids}"); } else { print "# Если закрепленного сообщения нет, то создать его и сохранить кеш\n"; if ($tmp = $tlg->sendMessage($rcpt)) { $ref = $tmp['message_id']; $tlg->pinChatMessage($rcpt, $ref); file_put_contents("/tmp/{$script}_telegram.tmp", "{$ref}: {$ids}"); } } } } else { print "# Нет аварий\n"; if ($ref) { print "# Если есть закрепленное сообщение, то закрыть его и удалить кеш\n"; $tlg->build(); $tlg->build("Активные аварии отсутствуют.\n"); $tlg->build("\nИнформация обновлена: " . date("Y-m-d H:i:s")); $tlg->editMessageText($rcpt, $ref); $tlg->unpinChatMessage($rcpt, $ref); unlink("/tmp/{$script}_telegram.tmp"); } } Обертки Zabbix и Telegram нужно подставить свои, но в принципе скрипт полный и рабочий. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Ser Posted September 26, 2022 · Report post Спасибо. Попробую разобраться. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...