DevOps / мониторинг / Zabbix

Скрипты Zabbix: автоматизация оповещений, webhook, Telegram и реакции на инциденты

Как использовать скрипты, webhook и actions для автоматизации алертов — от Telegram-уведомлений до runbook и безопасного auto-remediation. Внутри — готовый инструмент Zabbix Alert Copilot Lite на FastAPI.

Что такоеСкрипты Zabbix — действия, запускаемые вручную или автоматически при событиях мониторинга.
ЗачемWebhook, Telegram, диагностика, тикеты, runbook, auto-remediation.
ИнструментZabbix Alert Copilot Lite — FastAPI webhook-обработчик: классификация инцидентов + runbook + Telegram.
Безопасный стартСначала webhook + runbook, потом remote commands только через allowlist.
СтекFastAPI, Python 3.12, Docker, Telegram Bot API, Zabbix webhook JS.

Что такое скрипты Zabbix

Скрипты Zabbix — это способ выполнить заранее определённое действие из Zabbix: вручную из интерфейса, через меню хоста или события, либо автоматически через action при возникновении проблемы.

На практике скрипты используют для четырёх задач:

ОповещенияTelegram, email, Slack, Mattermost, Bitrix24, Service Desk.
ДиагностикаПроверить порт, собрать лог, показать статус сервиса, свободное место.
ИнтеграцииПередать событие через webhook, вызвать API, создать тикет, обновить CMDB.
RemediationВыполнить безопасное действие: перезапустить зависший сервис, запустить проверенный скрипт.

Современный подход лучше строить вокруг связки:

Trigger → Action → Webhook → Runbook → Проверка → Эскалация человеку

Такой сценарий снижает шум от алертов и превращает Zabbix из пассивного мониторинга в систему первичной реакции на инциденты.

Скрипты vs обычные уведомления

Обычных уведомлений достаточно, если задача простая: сообщить администратору о CPU, диске, агенте или сервисе. Скрипты и webhook нужны, когда после алерта требуется действие.

Алерт в TelegramMedia type / webhook
Создать задачу в Service DeskWebhook
Добавить контекст к алертуWebhook + внешний обработчик
Собрать диагностикуScript или zabbix_get
Перезапустить сервисRemote command — только через allowlist
Связать Zabbix с AI/LLMWebhook + внешний сервис
Массово управлять хостамиZabbix API + Ansible/Python

Если вы строите автоматизацию для продакшена, начинайте не с auto-restart, а с обогащения алертов: объяснение проблемы, вероятная причина, список проверок, ссылка на runbook.

Архитектура автоматизации Zabbix

Zabbix Trigger
      ↓
Zabbix Action
      ↓
Webhook / Script / Remote Command
      ↓
Zabbix Alert Copilot Lite (внешний обработчик)
      ↓
Telegram / Service Desk / Runbook / API
      ↓
Проверка результата и эскалация
  1. Zabbix фиксирует проблему: недоступен сервер, заполнен диск, не отвечает порт.
  2. Trigger переводит событие в статус problem.
  3. Action проверяет условия: severity, host group, tag, time period.
  4. Operation выполняет действие: отправляет webhook, сообщение или команду.
  5. Внешний обработчик нормализует событие и формирует runbook.
  6. Если проблема решена, recovery operation отправляет сообщение о восстановлении.

Zabbix webhook: лучший способ подключить внешнюю автоматизацию

Zabbix webhook — удобный способ передать событие мониторинга во внешнюю систему по HTTP. Через webhook можно отправить алерт в Telegram, создать тикет, вызвать n8n/Make/Zapier, передать данные в backend или подключить AI-обработчик.

Типовой JSON payload для webhook:

{
  "event_id":       "{EVENT.ID}",
  "event_name":     "{EVENT.NAME}",
  "event_status":   "{EVENT.STATUS}",
  "event_severity": "{EVENT.SEVERITY}",
  "host":           "{HOST.NAME}",
  "host_ip":        "{HOST.IP}",
  "trigger_id":     "{TRIGGER.ID}",
  "trigger_name":   "{TRIGGER.NAME}",
  "item_value":     "{ITEM.LASTVALUE}",
  "event_time":     "{EVENT.DATE} {EVENT.TIME}",
  "tags":           "{EVENT.TAGS}",
  "url":            "{$ZABBIX.URL}"
}

Такой формат удобен для анализа: его можно отправить в Telegram, Service Desk, базу инцидентов или AI-сервис.

Telegram-уведомления Zabbix

Простое уведомление показывает, что сломалось. Обогащённое — ещё и что делать.

Минимальный формат

🚨 Zabbix Problem

Host:     {HOST.NAME}
Problem:  {EVENT.NAME}
Severity: {EVENT.SEVERITY}
Time:     {EVENT.DATE} {EVENT.TIME}
Value:    {ITEM.LASTVALUE}

Обогащённый формат (с runbook)

🚨 High: Disk space is low

Host: web-01
IP:   10.0.0.15
Metric: /var usage = 92%
Likely cause: logs, backups, temporary files

First checks:
1. df -h
2. du -sh /var/log/* | sort -h
3. journalctl --disk-usage

Runbook:
- Проверить рост логов
- Очистить старые rotated logs
- Проверить backup jobs
- Если usage > 95%, эскалировать дежурному

Именно такой формат делает алерт полезным: инженер сразу понимает, что произошло и что делать.

Auto-remediation в Zabbix

Auto-remediation — автоматическое действие после обнаружения проблемы. Важно разделять два уровня.

Уровень 1. Безопасная автоматизация

Действия, которые ничего не ломают:

  • отправить уведомление;
  • собрать диагностику;
  • добавить контекст;
  • создать тикет;
  • предложить runbook;
  • запросить подтверждение человека.

Уровень 2. Исполнительная автоматизация

Действия, меняющие состояние системы (restart, delete, kill, reload). Допустимы только при соблюдении условий:

  • команда заранее проверена;
  • используется allowlist, а не wildcard;
  • ограничение по host group или tag;
  • логирование результата;
  • есть rollback или ручная эскалация;
  • команда не принимает произвольный ввод из алерта.

Zabbix Alert Copilot Lite

Готовый мини-инструмент, который можно запустить на своём сервере. Принимает webhook из Zabbix, классифицирует инцидент, формирует runbook и при необходимости отправляет сообщение в Telegram.

Что умеет

  • принимает HTTP POST из Zabbix webhook;
  • нормализует поля события;
  • классифицирует проблему: disk, cpu, memory, service, network, agent, database, unknown;
  • формирует human-readable runbook по категории;
  • возвращает структурированный JSON-ответ;
  • опционально отправляет сообщение в Telegram;
  • не выполняет destructive-команды.

Установка и запуск

Структура проекта

zabbix-alert-copilot-lite/
  app.py
  requirements.txt
  .env.example
  docker-compose.yml

requirements.txt

fastapi==0.115.6
uvicorn==0.32.1
requests==2.32.3
python-dotenv==1.0.1

.env.example

TELEGRAM_BOT_TOKEN=
TELEGRAM_CHAT_ID=
PUBLIC_BASE_URL=https://alerts.example.com

app.py

import os
from typing import Dict, Any, List

import requests
from dotenv import load_dotenv
from fastapi import FastAPI, Request, HTTPException
from pydantic import BaseModel

load_dotenv()

app = FastAPI(title="Zabbix Alert Copilot Lite")

TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN", "")
TELEGRAM_CHAT_ID   = os.getenv("TELEGRAM_CHAT_ID", "")


class ZabbixEvent(BaseModel):
    event_id:       str | None = None
    event_name:     str | None = None
    event_status:   str | None = None
    event_severity: str | None = None
    host:           str | None = None
    host_ip:        str | None = None
    trigger_id:     str | None = None
    trigger_name:   str | None = None
    item_value:     str | None = None
    event_time:     str | None = None
    tags:           str | None = None
    url:            str | None = None


def classify_incident(text: str) -> str:
    value = text.lower()
    rules = {
        "disk":     ["disk", "space", "filesystem", "vfs.fs", "диск", "место"],
        "cpu":      ["cpu", "processor", "load", "процессор", "нагрузка"],
        "memory":   ["memory", "ram", "swap", "память"],
        "service":  ["service", "nginx", "apache", "mysql", "postgres", "systemd"],
        "network":  ["icmp", "ping", "unreachable", "snmp", "network", "сеть"],
        "agent":    ["zabbix agent", "agent is not", "agent unavailable", "агент"],
        "database": ["database", "postgresql", "mysql", "db", "база"],
    }
    for category, keywords in rules.items():
        if any(k in value for k in keywords):
            return category
    return "unknown"


def build_runbook(category: str) -> List[str]:
    runbooks = {
        "disk": [
            "Проверить свободное место: df -h",
            "Найти большие директории: du -sh /* 2>/dev/null | sort -h",
            "Проверить журналы: journalctl --disk-usage",
            "Проверить ротацию логов и backup jobs",
            "Если usage > 95% — эскалировать дежурному"
        ],
        "cpu": [
            "Проверить нагрузку: uptime и top",
            "Найти процессы: ps aux --sort=-%cpu | head",
            "Проверить недавние deploy/cron jobs",
            "Сравнить с историческими графиками Zabbix",
            "Если нагрузка держится > 10 мин — создать incident ticket"
        ],
        "memory": [
            "Проверить память: free -m",
            "Найти процессы: ps aux --sort=-%mem | head",
            "Проверить OOM events: dmesg -T | grep -i kill",
            "Проверить swap и memory leak",
            "Не перезапускать без подтверждения владельца"
        ],
        "service": [
            "Проверить статус: systemctl status <service>",
            "Проверить логи: journalctl -u <service> -n 100",
            "Проверить порт: ss -lntp",
            "Проверить конфигурацию сервиса",
            "Restart — только через allowlist и после проверки"
        ],
        "network": [
            "Проверить ping и packet loss",
            "Проверить порт: nc -vz host port",
            "Проверить маршрутизацию и DNS",
            "Для SNMP проверить community/user и ACL",
            "Если недоступна группа устройств — проверить канал"
        ],
        "agent": [
            "Проверить статус: systemctl status zabbix-agent2",
            "Проверить конфиг Server/ServerActive/Hostname",
            "Проверить порт 10050/10051 и firewall",
            "Проверить логи агента",
            "Перезапуск — только проверенной командой"
        ],
        "database": [
            "Проверить доступность базы и порт",
            "Проверить активные подключения",
            "Проверить slow queries и locks",
            "Проверить свободное место на диске",
            "Эскалировать DBA при повторении инцидента"
        ],
        "unknown": [
            "Открыть событие в Zabbix, проверить trigger expression",
            "Посмотреть последние значения item",
            "Проверить логи Zabbix server/proxy/agent",
            "Сравнить с соседними событиями по времени",
            "Добавить tag к trigger для улучшения классификации"
        ]
    }
    return runbooks.get(category, runbooks["unknown"])


def normalize_severity(severity: str | None) -> str:
    return severity.strip().title() if severity else "Unknown"


def make_message(event: ZabbixEvent, category: str, runbook: List[str]) -> str:
    runbook_text = "\n".join([f"{i+1}. {s}" for i, s in enumerate(runbook)])
    zabbix_link  = ""
    if event.url and event.trigger_id and event.event_id:
        zabbix_link = (
            f"\n\nOpen in Zabbix: {event.url}"
            f"/tr_events.php?triggerid={event.trigger_id}"
            f"&eventid={event.event_id}"
        )
    return (
        f"🚨 Zabbix {event.event_status or 'PROBLEM'}\n\n"
        f"Severity: {normalize_severity(event.event_severity)}\n"
        f"Host:     {event.host or 'unknown'}\n"
        f"IP:       {event.host_ip or 'n/a'}\n"
        f"Problem:  {event.event_name or event.trigger_name or 'Unknown'}\n"
        f"Category: {category}\n"
        f"Value:    {event.item_value or 'n/a'}\n"
        f"Time:     {event.event_time or 'n/a'}\n\n"
        f"Runbook:\n{runbook_text}{zabbix_link}"
    )


def send_telegram(message: str) -> bool:
    if not TELEGRAM_BOT_TOKEN or not TELEGRAM_CHAT_ID:
        return False
    resp = requests.post(
        f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage",
        json={"chat_id": TELEGRAM_CHAT_ID, "text": message, "disable_web_page_preview": True},
        timeout=10
    )
    resp.raise_for_status()
    return True


@app.get("/health")
def health() -> Dict[str, str]:
    return {"status": "ok"}


@app.post("/zabbix")
async def zabbix_webhook(request: Request) -> Dict[str, Any]:
    try:
        payload = await request.json()
    except Exception:
        raise HTTPException(status_code=400, detail="Invalid JSON")

    event    = ZabbixEvent(**payload)
    text     = " ".join(filter(None, [event.event_name, event.trigger_name, event.item_value, event.tags]))
    category = classify_incident(text)
    runbook  = build_runbook(category)
    message  = make_message(event, category, runbook)

    telegram_sent = False
    try:
        telegram_sent = send_telegram(message)
    except Exception:
        pass

    return {
        "ok":            True,
        "category":      category,
        "severity":      normalize_severity(event.event_severity),
        "telegram_sent": telegram_sent,
        "runbook":       runbook,
        "message":       message
    }

docker-compose.yml

services:
  zabbix-alert-copilot-lite:
    image: python:3.12-slim
    working_dir: /app
    volumes:
      - ./:/app
    command: sh -c "pip install -r requirements.txt && uvicorn app:app --host 0.0.0.0 --port 8080"
    ports:
      - "8080:8080"
    env_file:
      - .env
    restart: unless-stopped

Запуск

cp .env.example .env
# заполните TELEGRAM_BOT_TOKEN и TELEGRAM_CHAT_ID
docker compose up -d
curl http://localhost:8080/health

Тестовый запрос

curl -X POST http://localhost:8080/zabbix \
  -H 'Content-Type: application/json' \
  -d '{
    "event_id":       "12345",
    "event_name":     "Disk space is low on /var",
    "event_status":   "PROBLEM",
    "event_severity": "High",
    "host":           "web-01",
    "host_ip":        "10.0.0.15",
    "trigger_id":     "67890",
    "item_value":     "92%",
    "event_time":     "2026-05-24 14:20",
    "url":            "https://zabbix.example.com"
  }'

Webhook JavaScript для Zabbix

В Zabbix создайте media type типа Webhook и используйте этот JavaScript как основу. Замените URL на адрес вашего сервиса.

var params = JSON.parse(value);

var request = new HttpRequest();
request.addHeader('Content-Type: application/json');

var payload = {
    event_id:       params.event_id,
    event_name:     params.event_name,
    event_status:   params.event_status,
    event_severity: params.event_severity,
    host:           params.host,
    host_ip:        params.host_ip,
    trigger_id:     params.trigger_id,
    trigger_name:   params.trigger_name,
    item_value:     params.item_value,
    event_time:     params.event_time,
    tags:           params.tags,
    url:            params.url
};

var response = request.post(
    'https://alerts.example.com/zabbix',
    JSON.stringify(payload)
);

if (request.getStatus() < 200 || request.getStatus() >= 300) {
    throw 'Webhook failed: ' + request.getStatus() + ' — ' + response;
}

return response;

Параметры media type

event_id{EVENT.ID}
event_name{EVENT.NAME}
event_status{EVENT.STATUS}
event_severity{EVENT.SEVERITY}
host{HOST.NAME}
host_ip{HOST.IP}
trigger_id{TRIGGER.ID}
item_value{ITEM.LASTVALUE}
event_time{EVENT.DATE} {EVENT.TIME}
urlhttps://zabbix.example.com

Как настроить action в Zabbix

  1. Откройте Alerts → Media types.
  2. Создайте media type типа Webhook.
  3. Добавьте параметры события и вставьте JavaScript webhook.
  4. Откройте Alerts → Actions → Trigger actions.
  5. Создайте action с нужными условиями.
  6. В Operations добавьте отправку через созданный media type.
  7. Настройте recovery operation для сообщения о восстановлении.
  8. Проверьте отправку на тестовом trigger.

Рекомендуемые условия для первого запуска

  • severity: High или Disaster;
  • host group: production;
  • tag: autopilot=enabled;
  • recovery operation: отправлять сообщение о восстановлении.

Так вы не подключите автоматизацию сразу ко всем событиям и сможете контролировать качество алертов.

Безопасность: как не превратить скрипты Zabbix в риск

Правила безопасной автоматизации

  • не передавайте в shell произвольный текст из события;
  • не используйте wildcard без необходимости;
  • разрешайте только конкретные команды из allowlist;
  • разделяйте роли: просмотр, диагностика, remediation;
  • логируйте каждый запуск;
  • используйте системного пользователя с минимальными правами;
  • для destructive-действий требуйте подтверждение человека;
  • начинайте с webhook и runbook, а не с auto-restart.

Плохо

system.run[{EVENT.NAME}]

Лучше

system.run[/usr/local/bin/zbx-check-nginx-status]

Ещё лучше: отправлять событие во внешний обработчик, который классифицирует инцидент и предлагает runbook, а команды восстановления запускать только после подтверждения.

Zabbix API: когда он нужен

Zabbix API нужен, когда автоматизация должна не только реагировать на событие, но и управлять объектами Zabbix.

Получить текущие проблемыZabbix API
Отправить внешнюю метрикуzabbix_sender
Проверить значение itemzabbix_get
Массово создать хостыAPI + Python/Ansible
Управлять maintenance windowsZabbix API
Создать AI-дашборд инцидентовAPI + backend

Webhook нужен для реакции на событие. Zabbix API нужен для управления объектами и получения данных: хостов, проблем, истории, шаблонов, maintenance windows.

Примеры сценариев автоматизации

Сценарий 1. Диск почти заполнен

ТриггерСвободного места меньше 10%
ActionWebhook → Alert Copilot Lite
Безопасно автоматизироватьСбор диагностики, создание тикета
Только с подтверждениемУдаление файлов

Сценарий 2. HTTP endpoint не отвечает

ТриггерWeb scenario failed или TCP port недоступен
RunbookDNS → порт → nginx/apache → upstream → последние deploy
RemediationRestart только через allowlist и ограничение по host group

Сценарий 3. Zabbix agent недоступен

Триггерagent unavailable
RunbookДоступность хоста → порт 10050 → firewall → zabbix-agent2 → конфиг
Польза CopilotОтличает проблему агента от проблемы сети, предлагает разные действия

Сценарий 4. Проблема с базой данных

ТриггерPostgreSQL/MySQL unavailable, high connections, replication lag
RunbookПорт и процесс → connections → locks → место → последние изменения
RemediationСобирать диагностику, эскалировать DBA — не перезапускать автоматически

Частые ошибки при настройке скриптов Zabbix

Слишком широкий actionСрабатывает на все события → шум. Ограничьте по severity, host group, tags.
Нет recovery operationКоманда получает алерт, но не получает сообщение о восстановлении. Настройте recovery operation.
Webhook не логирует ошибкиНепонятно, где потерялось сообщение. Логируйте HTTP status, response body и event_id.
Скрипт без allowlistРиск безопасности. Разрешайте только конкретные команды.
Нет тестового окруженияСкрипт проверяется на production. Создайте отдельную host group для тестовых алертов.

Частые вопросы о скриптах Zabbix

Что такое zabbix скрипты?

Скрипты Zabbix — заранее заданные действия, которые можно запускать вручную или автоматически при событиях мониторинга. Используются для диагностики, уведомлений, webhook-интеграций и безопасной реакции на инциденты.

Как настроить webhook в Zabbix?

Создайте media type типа Webhook, добавьте параметры события, вставьте JavaScript-обработчик и подключите media type к action в разделе Trigger actions.

Можно ли отправлять уведомления Zabbix в Telegram?

Да. Через webhook, Telegram Bot API или готовую интеграцию. Для продакшена лучше отправлять не только текст алерта, но и runbook с первыми действиями.

Что такое auto-remediation в Zabbix?

Auto-remediation — автоматическое действие при проблеме: сбор диагностики, создание тикета, отправка webhook или выполнение безопасной команды. Начинайте с диагностики и runbook, а не с автоматического перезапуска сервисов.

Безопасно ли запускать remote commands в Zabbix?

Безопасно только при строгих ограничениях: allowlist команд, минимальные права, логирование, ограничение по host group/tags и отсутствие произвольных параметров из события.

Чем webhook лучше обычного email-уведомления?

Webhook передаёт структурированные данные во внешний сервис, позволяет обогащать алерт, создавать тикеты, группировать события и подключать AI-обработку. Email подходит только для простых уведомлений.

Можно ли подключить AI к Zabbix?

Да. Самый безопасный способ — отправлять событие через webhook во внешний обработчик, который формирует summary, runbook и рекомендации. Выполнение команд лучше оставлять под контролем человека.

Что лучше: Zabbix API или webhook?

Webhook нужен для реакции на событие. Zabbix API нужен для управления объектами Zabbix: хостами, шаблонами, проблемами, историей, maintenance windows.

Zabbix / мониторинг / автоматизация

Хотите автоматизировать Zabbix без хаоса в алертах?

Помогу подключить webhook, настроить Telegram-уведомления с runbook, классифицировать инциденты и внедрить безопасный auto-remediation. Первый шаг — обогащение алертов и диагностика. Только после этого — безопасные команды восстановления.

Другие статьи