zabbix_sender over HTTP — как послать данные в Zabbix по HTTP|S

В этой статье я приведу возможное решение проблемы для многих системных администраторов, которые используют систему мониторинга Zabbix. Особенно пригодится для тех, кто осуществляет мониторинг разных программ в Zabbix: системы телефонии, разные регламентные операции с БД, 1С (да, да, такие вот мы извращенцы люди с нестандартным мышлением, что мониторим 1С в Zabbix). Сам мучался делая Powershell-скрипты, использую для отсылки zabbix_sender.exe. Страшные были времена.

Как мы до этого дошли


Пользуюсь данной системой не первый год. В начале использовали для мониторинга доступности (ага, таким комбайном делали icmp-запросы и все). Сейчас используем почти весь функционал, карты, инвентаризацию, отчеты. С недавнего времени стали прикручивать мониторинг бэкапов (не только Linux-систем, но и разных Windows), мониторинг разных программ (кассовые программы в рознице), обменов, синхронизаций. И каждый раз приходилось писать скрипты, потому что многие программы не могли сами запускать zabbix_sender.exe с нужными параметрами (особенно касается 1С). Для мониторинга этих скриптов писались другие скрипты. Программа экспортирует что-то в файл, скрипт его парсит, отправляет все через zabbix_sender.

Каждый раз мне — как системному администратору — приходилось делать все скрипты. Программисты 1С же просто писали файлики, логика была вся на мне. Меня это как и любого ленивого системного администратора не устраивало.
Я всегда негодовал (особенно в начале), почему нет веб-интерфейса для отправки значений в Zabbix? А теперь все проще — ну раз нет, так напишем!

Реализация


Оправдания, извинения
Сразу скажу, я не PHP-программист, поэтому у толковых программистов код может вызвать кровотечения из области глаз. Также не стоит данное решение подвергать большой нагрузке, для каждого значения запускается отдельный экземпляр zabbix_sender, если нужно отправить сразу много значений — возможно стоит поискать в API и устанавливать одну сессию, без разрыва. Таким способом мы получаем примерно 200 параметров за минуту, пока полет отличный!

Приступим! Создаем папку zabbix_sender на сервер zabbix (у меня папка /var/www/zabbix, не забываем про root-права):

mkdir /var/www/zabbix/zabbix_sender
chown www-data:www-data /var/www/zabbix/zabbix_sender

Создаем файл index.php, содержание в
спойлере
<?php
function get_client_ip() {
    $ipaddress = '';
    if (getenv('HTTP_CLIENT_IP'))
        $ipaddress = getenv('HTTP_CLIENT_IP');
    else if(getenv('HTTP_X_FORWARDED_FOR'))
        $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
    else if(getenv('HTTP_X_FORWARDED'))
        $ipaddress = getenv('HTTP_X_FORWARDED');
    else if(getenv('HTTP_FORWARDED_FOR'))
        $ipaddress = getenv('HTTP_FORWARDED_FOR');
    else if(getenv('HTTP_FORWARDED'))
       $ipaddress = getenv('HTTP_FORWARDED');
    else if(getenv('REMOTE_ADDR'))
        $ipaddress = getenv('REMOTE_ADDR');
    else
        $ipaddress = 'UNKNOWN';
    return $ipaddress;
}


//header("Content-type: text/xml; charset=windows-1251");
$server=$_GET['server'];
$key=$_GET['key'];
$value=$_GET['value'];
$zabbix_server_address="zabbix.domain.com";

if (empty($server)){
        echo "parametr SERVER is EMPTY";
        $ip_address=get_client_ip();
        $error_msg= date('Y-m-d H:i:s') . " - ZABBIX_SENDER[warning] - FROM: $ip_address; HTTP_PARAM: server=$server, key=$key, value=$value; ERROR: parametr SERVER is EMPTY\n";
        error_log($error_msg,3,"/var/log/apache2/zabbix_sender.log");
        exit;
}

if (empty($key)){
        echo "parametr KEY is EMPTY";
        $ip_address=get_client_ip();
        $error_msg= date('Y-m-d H:i:s') . " - ZABBIX_SENDER[warning] - FROM: $ip_address; HTTP_PARAM: server=$server, key=$key, value=$value; ERROR: parametr KEY is EMPTY\n";
        error_log($error_msg,3,"/var/log/apache2/zabbix_sender.log");
        exit;
}

if ($value==""){
        echo "parametr value is EMPTY";
        $ip_address=get_client_ip();
        $error_msg= date('Y-m-d H:i:s') . " - ZABBIX_SENDER[warning] - FROM: $ip_address; HTTP_PARAM: server=$server, key=$key, value=$value; ERROR: parametr VALUE is EMPTY\n";
        error_log($error_msg,3,"/var/log/apache2/zabbix_sender.log");
        exit;
}

$exec_str="/usr/local/bin/zabbix_sender -z $zabbix_server_address -p 10051 -s ".escapeshellarg($server)." -k ". escapeshellarg($key)." -o ". escapeshellarg($value);
exec($exec_str,$out, $err);
if ($err==0){
        echo "OK";
}
else {
        //print to html
        echo "ERROR:";
        echo "</br>";
        echo "server=$server, key=$key, value=$value";
        echo "</br>";
        var_dump($out);
        echo "</br>";
        var_dump($err);

        //Log error
        $ip_address=get_client_ip();
        $error_msg= date('Y-m-d H:i:s') . " - ZABBIX_SENDER[error] - FROM: $ip_address; HTTP_PARAM: server=$server, key=$key, value=$value; ERROR: zabbix_sender: $out[0]\n";
        error_log($error_msg,3,"/var/log/apache2/zabbix_sender.log");

}


Чтобы отослать значение. вам достаточно написать в браузере (или в программе, которая умеет делать HTTP GET-запрос) запрос вида zabbix.domain.com/zabbix_sender/index.php?server=myhost&key=testitem&value=11. Где server — хост в заббиксе (регистрозависимое имя!), key/value — название и значение item.

Подробнее или для интересующихся


Функция get_client_ip берет IP-адрес клиента, который послал (будем писать в лог для дебага при ошибках).

Всего две возможные ошибки. Ошибка при выполнении zabbix_sender, пишем в лог (который находится в /var/www/apache2/zabbix_sender.log)
ZABBIX_SENDER[error] - FROM: $ip_address; HTTP_PARAM: server=$server, key=$key, value=$value; ERROR: zabbix_sender

Нет какого-либо GET-параметр
ZABBIX_SENDER[warning] - FROM: $ip_address; HTTP_PARAM: server=$server, key=$key, value=$value; ERROR: parametr KEY is EMPTY

Где $ip_address — с какого IP-адреса послали значение, остальные параметры думаю понятные.

Мониторим систему мониторинга


Смотреть на ошибки после того как мониторинг не сработал — плохо, поэтому мы будем мониторить мониторинг.
Для этого добавляем в zabbix_agentd.conf:

UserParameter=zabbix_sender_web_status_error, grep -q 'ZABBIX_SENDER\[error\]' /var/log/apache2/zabbix_sender.log; echo $?;
UserParameter=zabbix_sender_web_status_warning, grep -q 'ZABBIX_SENDER\[warning\]' /var/log/apache2/zabbix_sender.log; echo $?;

Перезапускаем агента. Чтобы логи очищались раз в день (и ошибка висела только один день), проверяем чтобы был файл /etc/logrotate.d/apache2 с содержанием:

/var/log/apache2/*.log {
        daily
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 644 www-data www-data
        sharedscripts
        postrotate
                /etc/init.d/apache2 reload > /dev/null
        endscript
}

В хосте Zabbix Server добавляем два item:

image
image

И два триггера:




Напоследок


Итого мы получили новое API для отсылки значений в Zabbix. Теперь даем ссылку программистам zabbix.domain.com/zabbix_sender/index.php?server=myhost&key=testitem&value=11, создаем нужные Шаблоны, привязываем к хостам… Ну и еще много чего делаем, но уже без zabbix_sender, а с модным web API. Программисты могут сами отслеживать успех или неудачу доставки, если все хорошо, то веб-сервер вернет страничку «OK», если нет — сообщит какого параметра нет. Ну если совсем тяжело, то Zabbix сам скажет что у него ошибка.

P.S. Хочу услышать конструктивную критику, возможно, даже есть похожие решения, но я их не нашел.
Share post
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 12

    0
    exec("/usr/local/bin/zabbix_sender -z $zabbix_server_address -p 10051 -s $server -k $key -o $value",$out, $err);
    


    надо же передаваемые параметры заэскейпить? так можно любую команду выполнить.

    + вместо вызова утилиты zabbix_sender можно воспользоваться классом github.com/okitsu/php-zabbix-sender
      0
      Спасибо, исправил.
      $exec_str="/usr/local/bin/zabbix_sender -z $zabbix_server_address -p 10051 -s ".escapeshellarg($server)." -k ". escapeshellarg($key)." -o ". escapeshellarg($value);
      exec($exec_str,$out, $err);
      


      За ссылку спасибо, но думаю буду использовать только если начнутся проблемы с производительностью, предварительно сравнив тестами.
        0
        Я бы убрал реальную ссылку в комментарии.
          0
          Недоглядел, спасибо.
      0
      UserParameter=zabbix_sender_web_status_error, grep -q 'ZABBIX_SENDER\[error\]' /var/log/apache2/zabbix_sender.log; echo $?;
      UserParameter=zabbix_sender_web_status_warning, grep -q 'ZABBIX_SENDER\[warning\]' /var/log/apache2/zabbix_sender.log; echo $?;
      


      Чем вас logrt[] не устраивает?
        0
        Устраивает. Сложно было триггер придумать, чтобы «Ошибки за последний день, но чтобы ошибка уходила после очистки логов». Такие ошибки редкость, как только появляется — разбираюсь, потом чищу лог. Если знаете как — подскажите.
          0
          Вам нужно, чтобы приходила отбивка, и триггер не висел вечно в панели: триггер делается через две функции
          {server:item.str(«warning»)}=1 & {server:item.nodata(60)}=0 — как-то так, у вас будет возникать евент и через 60 сек должен переходить в ОК
            0
            Возможно и так. Спасибо!
        0
        неужели лучше еще ничего до сих пор нет?
          0
          Если стоит задача «Отправить в заббикс по HTTP\S значение» — судя по всему нет. Но есть реализации на других языках — python\perl

          Самое хорошее для 1С было бы реализовать такую библиотеку и выложить её в открытый доступ
        0
        Забыл приложить ссылку на github: github.com/allburov/zabbix_sender_over_http

        Only users with full accounts can post comments. Log in, please.