Что такое скрипты Zabbix
Скрипты Zabbix — это способ выполнить заранее определённое действие из Zabbix: вручную из интерфейса, через меню хоста или события, либо автоматически через action при возникновении проблемы.
На практике скрипты используют для четырёх задач:
Современный подход лучше строить вокруг связки:
Trigger → Action → Webhook → Runbook → Проверка → Эскалация человеку
Такой сценарий снижает шум от алертов и превращает Zabbix из пассивного мониторинга в систему первичной реакции на инциденты.
Скрипты vs обычные уведомления
Обычных уведомлений достаточно, если задача простая: сообщить администратору о CPU, диске, агенте или сервисе. Скрипты и webhook нужны, когда после алерта требуется действие.
Если вы строите автоматизацию для продакшена, начинайте не с auto-restart, а с обогащения алертов: объяснение проблемы, вероятная причина, список проверок, ссылка на runbook.
Архитектура автоматизации Zabbix
Zabbix Trigger
↓
Zabbix Action
↓
Webhook / Script / Remote Command
↓
Zabbix Alert Copilot Lite (внешний обработчик)
↓
Telegram / Service Desk / Runbook / API
↓
Проверка результата и эскалация
- Zabbix фиксирует проблему: недоступен сервер, заполнен диск, не отвечает порт.
- Trigger переводит событие в статус problem.
- Action проверяет условия: severity, host group, tag, time period.
- Operation выполняет действие: отправляет webhook, сообщение или команду.
- Внешний обработчик нормализует событие и формирует runbook.
- Если проблема решена, 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.NAME}{EVENT.STATUS}{EVENT.SEVERITY}{HOST.NAME}{HOST.IP}{TRIGGER.ID}{ITEM.LASTVALUE}{EVENT.DATE} {EVENT.TIME}https://zabbix.example.comКак настроить action в Zabbix
- Откройте Alerts → Media types.
- Создайте media type типа Webhook.
- Добавьте параметры события и вставьте JavaScript webhook.
- Откройте Alerts → Actions → Trigger actions.
- Создайте action с нужными условиями.
- В Operations добавьте отправку через созданный media type.
- Настройте recovery operation для сообщения о восстановлении.
- Проверьте отправку на тестовом 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.
Webhook нужен для реакции на событие. Zabbix API нужен для управления объектами и получения данных: хостов, проблем, истории, шаблонов, maintenance windows.
Примеры сценариев автоматизации
Сценарий 1. Диск почти заполнен
Сценарий 2. HTTP endpoint не отвечает
Сценарий 3. Zabbix agent недоступен
Сценарий 4. Проблема с базой данных
Частые ошибки при настройке скриптов Zabbix
Частые вопросы о скриптах 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.