Удобный мониторинг Syslog сообщений c сетевых железок в Zabbix

в 8:05, , рубрики: open source, rsyslog, syslog, zabbix, Блог компании Zabbix, Серверное администрирование, системное администрирование

Неотъемлемой частью сетевого мониторинга является сбор логов с контролируемых серверов и прочих железок. Ведь сколько бы мы ни создали отдельных элементов данных и триггеров к ним, в какой-то момент возникнет ситуация, что что-то важное мы упустили из виду и не контролируем. Итог: «У нас ничего не работает», а система мониторинга говорит, что все хорошо.

Поэтому первое, что хотелось сделать — собирать все логи в заббиксе, сгруппировав их по узлу сети для того, чтобы всегда можно было пробежаться по сообщениям глазами, не тратя время на доступ на оборудование.
Второе — обратить внимание и на те события, о которых и не подозреваешь.

Как это сделать на серверах или компьютерах, где установлен заббикс-агент, многие знают — есть встроенные элементы данных log[], logrt[].

Но как быть, когда нужно собирать логи с сетевого оборудования, на которое никак не водрузить Zabbix-agent’а? Вообще-то можно, конечно, настроить syslog-сервер на том же ПК, на которой есть заббикс-агент, а дальше при помощи log[] переносить эти данные в заббикс. Вот только элементы данных и триггеры по нему будут прикреплены к узлу сети с заббикс-агентом, что интуитивно малопонятно. А можно ли прикрепить эти данные непосредственно к сетевому устройству? Можно.

Для этого нам понадобится zabbix_sender, Zabbix API и rsyslog на машине с заббикс-сервером или заббикс-прокси. В качестве бонуса также получим быстрый контекстный переход в журнал syslog-сообщений с карты сети.
Как будет выглядеть результат? Ну, примерно вот так:
Контекстный вызов:
Удобный мониторинг Syslog сообщений c сетевых железок в Zabbix - 1

How to

Большими мазками архитектура решения выглядит вот так:
Удобный мониторинг Syslog сообщений c сетевых железок в Zabbix - 2
1. Все логи с сетевых устройств падают на сервер с Zabbix сервером или прокси, на котором по совместительству расположен rsyslog.
2. rsyslog запускаем скрипт, который определяет (3) с какого узла сети в Заббиксе пришло сообщение
4. Сообщение уходит в заббикс через утилиту zabbix_sender
Ну что, начнем «прорубать» путь сообщению от сетевой железки до заббикс

На сетевом оборудовании

Тут все просто. Укажите в качестве адресата для syslog-сообщений машину с Zabbix-сервером или Zabbix-proxy. Настройте оборудование на отсылку сообщений любых severity и facility.

На каком-нибудь D-Link'e это может выглядеть примерно вот так:

enable syslog
create syslog host 1 ipaddress 10.2.0.21 severity debug  state enable

А скажем на Cisco роутере вот так:

cisco1#
cisco1#config terminal
Enter configuration commands, one per line. End with CNTL/Z.
cisco1(config)#logging 10.2.0.21
cisco1(config)#service timestamps debug datetime localtime show-timezone msec
cisco1(config)#service timestamps log datetime localtime show-timezone msec
cisco1(config)#logging facility local3
cisco1(config)#logging trap informational
cisco1(config)#end

Настроили? Идем дальше.

В веб-интерфейсе Заббикса

Начнем с самого простого и понятного. В Zabbix’e создадим шаблон Template_Syslog и добавим в нем один единственный элемент данных:
Удобный мониторинг Syslog сообщений c сетевых железок в Zabbix - 3

Заполним поля следующим образом:

Поле Значение Примечание
Имя Syslog
Тип Zabbix траппер
Ключ syslog Важно, чтобы было именно такое имя (для дальнейшей корректной работы Zabbix API)
Тип информации Журнал(лог)
Формат времени в журнале(логе) yyyyxMMxddxhhxmmxssxxxxxx Маска для правильного определения даты по формату в RFC5424

Далее прикрепляем этот шаблон ко всем узлам сети, с которых будем собирать syslog-сообщения. Важно в интерфейсах указать те IP-адреса, с которых будут приходить логи в Заббикс. Иначе просто не получится идентифицировать источник сообщения.
Удобный мониторинг Syslog сообщений c сетевых железок в Zabbix - 4

Syslog-сервер

Настроим syslog-сервер на хосте с Zabbix-сервером. В нашем случае это распостраненный rsyslog, который идет во многих дистрибутивах Linux. Если у вас syslog-ng, то там все можно сделать практически так же.

В самом простом случае syslog-сервер раскладывает полученные сообщения по файлам в зависимости от facility и severity сообщений. Однако, есть и другие возможности. Например, в rsyslog существует возможность запуска произвольного скрипта для каждого сообщения. Этой функцией мы и воспользуемся.
Второй вопрос, который нужно решить — идентификация оборудования, чтобы определить, в лог какого узла добавлять сообщение в Заббиксе. Его мы решим, добавив в строчку с самим сообщением ip-адрес источника в квадратных скобах.

Для всего этого создадим конфиг-файл /etc/rsyslog.d/zabbix_rsyslog.conf

#add template for network devices
$template network-fmt,"%TIMESTAMP:::date-rfc3339% [%fromhost-ip%] %pri-text% %syslogtag%%msg%n"

#exclude unwanted messages:
:msg, contains, "Child connection from ::ffff:10.2.0.21" ~
:msg, contains, "exit after auth (ubnt): Disconnect received" ~
:msg, contains, "password auth succeeded for 'ubnt' from ::ffff:10.2.0.21" ~
:msg, contains, "exit before auth: Exited normally" ~
#action for every message:
if $fromhost-ip != '127.0.0.1' then ^/usr/local/bin/zabbix_syslog_lkp_host.pl;network-fmt     
& ~

Мы только что создали настройку для rsyslog, которая будет все сообщения полученные не с локального хоста форматировать определенным образом и запускать наш скрипт /usr/local/bin/zabbix_syslog_lkp_host.pl с syslog-сообщением в качестве аргумента.

Заодно в разделе #exclude unwanted messages мы можем отбрасывать засоряющие логин сообщения, если они заранее известны. Пара сообщений оставлена тут в качестве примера.

Под конец настройки rsyslog не забудьте еще раскомментировать следующие строки в файле /etc/rsyslog.conf для приема Syslog-сообщений по сети через UDP.:

$ModLoad imudp
$UDPServerRun 514

И все же, что делает скрипт /usr/local/bin/zabbix_syslog_lkp_host.pl, который мы указали запускать rsyslog'у? Если вкратце, он просто через zabbix_sender шлет данное сообщение на Zabbix_server или на Zabbix_proxy, ну вот примерно по такому шаблону:

/usr/bin/zabbix_sender -z *ИМЯСЕРВЕРА* -k syslog -o *SYSLOG-СООБЩЕНИЕ* -s *ИМЯУЗЛА*

Но откуда скрипту знать, какое будет *ИМЯУЗЛА* (т.е. к какому узлу крепить сообщение), ведь известен только IP-адрес, с которого пришло сообщение?
Для этого мы будем использовать Zabbix API, именно через него мы и сможем найти *ИМЯУЗЛА* по IP-адресу.

/usr/local/bin/zabbix_syslog_lkp_host.pl

#!/usr/bin/perl

use 5.010;
use strict;
use warnings;
use JSON::RPC::Legacy::Client;
use Data::Dumper;
use Config::General;
use CHI;
use List::MoreUtils qw (any);
use English '-no_match_vars';
use Readonly;
our $VERSION = 1.1;

Readonly my $CACHE_TIMEOUT => 600;
Readonly my $CACHE_DIR => '/tmp/zabbix_syslog_cache';

my $conf   = Config::General->new('/usr/local/etc/zabbix_syslog.cfg');
my %Config = $conf->getall;

#Authenticate yourself
my $client   = JSON::RPC::Legacy::Client->new();
my $url      = $Config{'url'} || die "URL is missing in zabbix_syslog.cfgn";
my $user     = $Config{'user'} || die "API user is missing in zabbix_syslog.cfgn";
my $password = $Config{'password'} || die "API user password is missing in zabbix_syslog.cfgn";
my $server = $Config{'server'} || die "server hostname is missing in zabbix_syslog.cfgn";
my $zabbix_sender = $Config{'zabbix_sender'} || '/usr/local/bin/zabbix_sender';

die "Problems with zabbix_sender binary: $ERRNOn"
  unless -e -x $zabbix_sender;    #check zabbix_sender exists and is executable

my $debug = $Config{'debug'};
my ( $authID, $response, $json );
my $id = 0;

my $message = shift @ARGV || die "Syslog message required as an argumentn";  #Grab syslog message from rsyslog

#get ip from message
my $ip;

#IP regex patter part
my $ipv4_octet = q/(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/;

if ( $message =~ / [ ((?:$ipv4_octet[.]){3}${ipv4_octet}) ]/msx ) {
    $ip = $1;
}
else {
    die "No IP in square brackets found in '$message', cannot continuen";
}

my $cache = CHI->new(
    driver   => 'File',
    root_dir => $CACHE_DIR,
);

my $hostname = $cache->get($ip);

if ( !defined $hostname ) {

    $authID = login();
    my @hosts_found;
    my $hostid;
    foreach my $host ( hostinterface_get() ) {

        $hostid = $host->{'hostid'};

        if ( any { /$hostid/msx } @hosts_found ) {
            next;
        }    #check if $hostid already is in array then skip(next)
        else { push @hosts_found, $hostid; }

###########now get hostname
        if ( get_zbx_trapper_syslogid_by_hostid($hostid) ) {

            my $result = host_get($hostid);

            #return hostname if possible
            if ( $result->{'host'} ) {

                if ( $result->{'proxy_hostid'} == 0 )    #check if host monitored directly or via proxy
                {
                    #lease $server as is
                }
                else {
                   #assume that rsyslogd and zabbix_proxy are on the same server
                    $server = 'localhost';
                }
                $hostname = $result->{'host'};
            }

        }

    }
    logout();
    $cache->set( $ip, $hostname, $CACHE_TIMEOUT );
}

system $zabbix_sender. ' -z '
  . $server
  . ' -k syslog -o ''
  . $message
  . '' -s '
  . $hostname;    #run  zabbix_sender

#______SUBS
sub login {

    $json = {
        jsonrpc => '2.0',
        method  => 'user.login',
        params  => {
            user     => $user,
            password => $password

        },
        id => $id++,
    };

    $response = $client->call( $url, $json );

    # Check if response was successful
    die "Authentication failedn" unless $response->content->{'result'};

    if ( $debug > 0 ) { print Dumper $response->content->{'result'}; }

    return $response->content->{'result'};

}

sub logout {

    $json = {
        jsonrpc => '2.0',
        method  => 'user.logout',
        params  => {},
        id      => $id++,
        auth    => $authID,
    };

    $response = $client->call( $url, $json );

    # Check if response was successful
    warn "Logout failedn" unless $response->content->{'result'};

    return;
}

sub hostinterface_get {

    $json = {

        jsonrpc => '2.0',
        method  => 'hostinterface.get',
        params  => {
            output => [ 'ip', 'hostid' ],
            filter => { ip => $ip, },

            #    limit => 1,
        },
        id   => $id++,
        auth => $authID,
    };

    $response = $client->call( $url, $json );

    if ( $debug > 0 ) { print Dumper $response; }

    # Check if response was successful (not empty array in result)
    if ( !@{ $response->content->{'result'} } ) {
        logout();
        die "hostinterface.get failedn";
    }

    return @{ $response->content->{'result'} }

}

sub get_zbx_trapper_syslogid_by_hostid {

    my $hostids = shift;

    $json = {
        jsonrpc => '2.0',
        method  => 'item.get',
        params  => {
            output  => ['itemid'],
            hostids => $hostids,
            search  => {
                'key_' => 'syslog',
                type   => 2,          #type => 2 is zabbix_trapper
                status => 0,

            },
            limit => 1,
        },
        id   => $id++,
        auth => $authID,
    };

    $response = $client->call( $url, $json );
    if ( $debug > 0 ) { print Dumper $response; }

    # Check if response was successful
    if ( !@{ $response->content->{'result'} } ) {
        logout();
        die "item.get failedn";
    }

    #return itemid of syslog key (trapper type)
    return ${ $response->content->{'result'} }[0]->{itemid};
}

sub host_get {
    my $hostids = shift;

    $json = {

        jsonrpc => '2.0',
        method  => 'host.get',
        params  => {
            hostids => [$hostids],
            output  => [ 'host', 'proxy_hostid', 'status' ],
            filter => { status => 0, },    # only use hosts enabled
            limit  => 1,
        },
        id => $id++,
        auth => $authID,
    };

    $response = $client->call( $url, $json );

    if ( $debug > 0 ) { print Dumper $response; }

    # Check if response was successful
    if ( !$response->content->{'result'} ) {
        logout();
        die "host.get failedn";
    }
    return ${ $response->content->{'result'} }[0];    #return result
}

Копируем скрипт на сервер по пути /usr/local/bin/zabbix_syslog_lkp_host.pl, также создаем конфигурационный файл
/usr/local/etc/zabbix_syslog.cfg с параметрами подключения к Заббиксу через API. Конфиг будет выглядеть примерно вот так:

url = http://zabbix.local/zabbix/api_jsonrpc.php
user = api_user
password = password
server = zabbix.local
debug=0
zabbix_sender= /usr/bin/zabbix_sender

Скрипт использует несколько модулей Perl из CPAN, чтобы установить их выполните команды:

PERL_MM_USE_DEFAULT=1 perl -MCPAN -e 'install Readonly'
PERL_MM_USE_DEFAULT=1 perl -MCPAN -e 'install CHI'
PERL_MM_USE_DEFAULT=1 perl -MCPAN -e 'install JSON::RPC::Legacy::Client'
PERL_MM_USE_DEFAULT=1 perl -MCPAN -e 'install Config::General'

Также настраиваем права на эти наши новые файлы:

chmod +x /usr/local/bin/zabbix_syslog_lkp_host.pl
chown zabbix:zabbix /usr/local/etc/zabbix_syslog.cfg
chmod 700 /usr/local/etc/zabbix_syslog.cfg

Все готово для отправки сообщений в Заббикс, осталось только перезагрузить rsyslog:

service rsyslog restart

С этого момента мы уже можем увидеть сообщения в заббиксе отдельно для каждого узла сети, открывая Последние данные -> нужный узел сети -> Syslog
Удобный мониторинг Syslog сообщений c сетевых железок в Zabbix - 5

Триггеры

Возможность чтения логов в системе без хождения по интерфейсам оборудования — это хорошо (не говоря даже о том, что как правило логи на оборудовании лежат в памяти и не переживают ребут), но давайте не забудем и про триггеры. Как и в случае других протоколов они помогут нам не проспать какое-нибудь судьбоносное сообщение на нашей сети.

У каждого оборудования и у каждого производителя оборудования сообщения свои, поэтому, как искать важное сообщение, не зная, как оно выглядит? А вот следующим образом:
Все сообщения syslog классифицируются при помощи атрибута severity, который согласно RFC5424 может принимать следующие значения:

0 Emergency: system is unusable
1 Alert: action must be taken immediately
2 Critical: critical conditions
3 Error: error conditions
4 Warning: warning conditions
5 Notice: normal but significant condition
6 Informational: informational messages
7 Debug: debug-level messages

есть у severity не только численное, но и текстовое сокращенное обозначение, присутствующее в окончательном сообщении, которое передается в Zabbix через zabbix_sender.
Таким образом, мы можем искать те сообщения, которым сама железка (то есть ее производитель) присвоила достаточно высокую важность, и оповещать о них. Для этого в наш шаблон Template_Syslog добавим триггеры, для оповещения о всех событиях с severity=warning и выше:

Удобный мониторинг Syslog сообщений c сетевых железок в Zabbix - 6

Последнее, что осталось сделать — это настроить оповещение (действие) об этих новых syslog-сообщениях. В условиях укажем, что имя триггера содержит [SYSLOG], и что отправлять сообщение нужно через электронную почту.

Удобный мониторинг Syslog сообщений c сетевых железок в Zabbix - 7

Удобный мониторинг Syslog сообщений c сетевых железок в Zabbix - 8

Удобный мониторинг Syslog сообщений c сетевых железок в Zabbix - 9

В итоге, каждый раз, когда в syslog упадет сообщение высокой важности, мы будем получать сообщение вида:
Удобный мониторинг Syslog сообщений c сетевых железок в Zabbix - 10
И кстати, наш шаблон с триггерами по критичности аварий уже готов:

Template_Syslog

<?xml version="1.0" encoding="UTF-8"?>
<zabbix_export>
    <version>2.0</version>
    <date>2015-03-13T14:27:56Z</date>
    <groups>
        <group>
            <name>Templates</name>
        </group>
    </groups>
    <templates>
        <template>
            <template>Template_Syslog</template>
            <name>Template_Syslog</name>
            <description/>
            <groups>
                <group>
                    <name>Templates</name>
                </group>
            </groups>
            <applications>
                <application>
                    <name>Log</name>
                </application>
            </applications>
            <items>
                <item>
                    <name>Syslog</name>
                    <type>2</type>
                    <snmp_community/>
                    <multiplier>0</multiplier>
                    <snmp_oid/>
                    <key>syslog</key>
                    <delay>0</delay>
                    <history>3</history>
                    <trends>365</trends>
                    <status>0</status>
                    <value_type>2</value_type>
                    <allowed_hosts/>
                    <units/>
                    <delta>0</delta>
                    <snmpv3_contextname/>
                    <snmpv3_securityname/>
                    <snmpv3_securitylevel>0</snmpv3_securitylevel>
                    <snmpv3_authprotocol>0</snmpv3_authprotocol>
                    <snmpv3_authpassphrase/>
                    <snmpv3_privprotocol>0</snmpv3_privprotocol>
                    <snmpv3_privpassphrase/>
                    <formula>1</formula>
                    <delay_flex/>
                    <params/>
                    <ipmi_sensor/>
                    <data_type>0</data_type>
                    <authtype>0</authtype>
                    <username/>
                    <password/>
                    <publickey/>
                    <privatekey/>
                    <port/>
                    <description/>
                    <inventory_link>0</inventory_link>
                    <applications>
                        <application>
                            <name>Log</name>
                        </application>
                    </applications>
                    <valuemap/>
                    <logtimefmt>yyyyxMMxddxhhxmmxssxxxxxx</logtimefmt>
                </item>
            </items>
            <discovery_rules/>
            <macros/>
            <templates/>
            <screens/>
        </template>
    </templates>
    <triggers>
        <trigger>
            <expression>({Template_Syslog:syslog.str(.alert)}=1)and({Template_Syslog:syslog.nodata(900)}=0)</expression>
            <name>[SYSLOG] Alert message received</name>
            <url/>
            <status>0</status>
            <priority>4</priority>
            <description/>
            <type>0</type>
            <dependencies/>
        </trigger>
        <trigger>
            <expression>({Template_Syslog:syslog.str(.crit)}=1)and({Template_Syslog:syslog.nodata(900)}=0)</expression>
            <name>[SYSLOG] Critical message received</name>
            <url/>
            <status>0</status>
            <priority>3</priority>
            <description/>
            <type>0</type>
            <dependencies/>
        </trigger>
        <trigger>
            <expression>({Template_Syslog:syslog.str(.emerg)}=1)and({Template_Syslog:syslog.nodata(900)}=0)</expression>
            <name>[SYSLOG] Emergency message received</name>
            <url/>
            <status>0</status>
            <priority>5</priority>
            <description/>
            <type>0</type>
            <dependencies/>
        </trigger>
        <trigger>
            <expression>({Template_Syslog:syslog.str(.err)}=1)and({Template_Syslog:syslog.nodata(900)}=0)</expression>
            <name>[SYSLOG] Error received</name>
            <url/>
            <status>0</status>
            <priority>2</priority>
            <description/>
            <type>0</type>
            <dependencies/>
        </trigger>
        <trigger>
            <expression>({Template_Syslog:syslog.str(.warning)}=1)and({Template_Syslog:syslog.nodata(900)}=0)</expression>
            <name>[SYSLOG] Warning received</name>
            <url/>
            <status>0</status>
            <priority>1</priority>
            <description/>
            <type>0</type>
            <dependencies/>
        </trigger>
    </triggers>
</zabbix_export>

Конечно, не обязательно отлавливать все сообщения warning, error, critical и так далее. Это просто обобщенный вариант, который помогает не упустить что-то нештатное. Используя функции триггеров iregxp(), regxp(), str(), всегда можно фиксировать в логах более специфические события.

Автоматическое крепление к карте

Затронем еще один важный момент, который упрощает работу с syslog-сообщениями — контекстный переход с карты сети.

Удобный мониторинг Syslog сообщений c сетевых железок в Zabbix - 11
Можно потратить день-другой и выстрадать добавление URL-ссылок для каждого узла сети на его syslog элемент данных руками:
Удобный мониторинг Syslog сообщений c сетевых железок в Zabbix - 12

Но скорее руки отсохнут кликать по мышке, либо умом тронешься. Лучше вновь обратимся к Zabbix API за помощью в автоматизации сего рутинного дела:
Для этого накидаем скрипт, который будет
1) Брать все элементы карты сети
2) Для всех элементов типа узел сети проверять, нет ли у него элемента данных с key=syslog
3) Если есть, добавлять к списку существующих URL ссылку на просмотр этого элемента данных (если URL на Syslog уже есть, то ничего не делать)
Когда скрипт будет готов, мы развернем его только на Zabbix-server'е:

/usr/local/bin/zabbix_syslog_create_urls.pl

#!/usr/bin/perl
#fixed URL for ZBX 2.4

use 5.010;
use strict;
use warnings;
use JSON::RPC::Legacy::Client;
use Data::Dumper;
use Config::General;
our $VERSION = 1.1;
my $conf   = Config::General->new('/usr/local/etc/zabbix_syslog.cfg');
my %Config = $conf->getall;

#Authenticate yourself
my $client   = JSON::RPC::Legacy::Client->new();
my $url      = $Config{'url'} || die "URL is missing in zabbix_syslog.cfgn";
my $user     = $Config{'user'} || die "API user is missing in zabbix_syslog.cfgn";
my $password = $Config{'password'}   || die "API user password is missing in zabbix_syslog.cfgn";
my $server = $Config{'server'}   || die "server hostname is missing in zabbix_syslog.cfgn";

my $debug = $Config{'debug'};
my ( $authID, $response, $json );
my $id = 0;



$authID = login();

my $syslog_url_base = 'history.php?action=showvalues';

    my @selements;

    foreach my $map ( @{ map_get_extended() } ) {
        my $mapid=$map->{sysmapid};
        #next unless ($mapid == 120 or $mapid == 116); #debug
       #put all mapelements into array @selements (so you can update map later!)
        @selements = @{ $map->{selements} };

        foreach my $selement (@selements) {
            my $syslog_button_exists = 0;

            if ( $debug > 0 ) {
                print 'Object ID: '
                  . $selement->{selementid}
                  . ' Type: '
                  . $selement->{elementtype}
                  . ' Elementid '
                  . $selement->{elementid} . " n";
            }

            # elementtype=0 hosts
            if ( $selement->{elementtype} == 0 ) {

                my $hostid = $selement->{elementid};

                my $itemid = get_syslogid_by_hostid($hostid);
                if ($itemid) {

                    #and add urls:

                    my $syslog_exists = 0;
                    foreach my $syslog_url ( @{ $selement->{urls} } ) {
                        $syslog_exists = 0;

                        if ( $syslog_url->{name} =~ 'Syslog' ) {

                            $syslog_exists = 1;
                            $syslog_url->{'name'} = 'Syslog';

                            $syslog_url->{'url'} =
                                $syslog_url_base
                              . '&itemids['
                              . $itemid . ']='
                              . $itemid;
                        }
                    }
                    if ( $syslog_exists == 0 ) {

                        #syslog item doesn't exist... add it
                        push @{ $selement->{urls} },
                          {
                            'name' => 'Syslog',
                            'url'  => $syslog_url_base
                              . '&itemids['
                              . $itemid . ']='
                              . $itemid
                          };
                    }

                }

            }

        }
            map_update($mapid,@selements);
    }



logout();

#______SUBS
sub get_syslogid_by_hostid {
    my $hostids = shift;

    $json = {
        jsonrpc => '2.0',
        method  => 'item.get',
        params  => {
            output  => ['itemid'],
            hostids => $hostids,
            search  => { 'key_' => 'syslog' },
            limit   => 1,
        },
        id   => $id++,
        auth => $authID,
    };

    $response = $client->call( $url, $json );

    # Check if response was successful
    if ( !$response->content->{'result'} ) {
        logout();
        die "item.get failedn";
    }

    #return itemid of syslog key (trapper type)
    return ${ $response->content->{'result'} }[0]->{itemid};
}

sub login {

    $json = {
        jsonrpc => '2.0',
        method  => 'user.login',
        params  => {
            user     => $user,
            password => $password

        },
        id => $id++,
    };

    $response = $client->call( $url, $json );

    # Check if response was successful
    die "Authentication failedn" unless $response->content->{'result'};

    if ( $debug > 0 ) { print Dumper $response->content->{'result'}; }

    return $response->content->{'result'};

}

sub map_get {

    #retrieve all maps
    $json = {
        jsonrpc => '2.0',
        method  => 'map.get',
        params  => {
            output => ['sysmapid']
        },
        id   => $id++,
        auth => "$authID",
    };

    $response = $client->call( $url, $json );

    # Check if response was successful
    if ( !$response->content->{'result'} ) {
        logout();
        die "map.get failedn";
    }

    if ( $debug > 1 ) { print Dumper $response->content->{result}; }
    return $response->content->{result};

}

sub logout {

    $json = {
        jsonrpc => '2.0',
        method  => 'user.logout',
        params  => {},
        id      => $id++,
        auth    => $authID,
    };

    $response = $client->call( $url, $json );

    # Check if response was successful
    warn "Logout failedn" unless $response->content->{'result'};

    return;
}

sub map_get_extended {
    $json = {
        jsonrpc => '2.0',
        method  => 'map.get',
        params  => {
            selectSelements => 'extend',
            #sysmapids       => $map,
        },
        id   => $id++,
        auth => $authID,
    };

    $response = $client->call( $url, $json );

    # Check if response was successful
    if ( !$response->content->{'result'} ) {
        logout();
        die "map.get failedn";
    }
    if ( $debug > 1 ) {

        print Dumper $response->content->{'result'};
    }

    return $response->content->{'result'};
}

sub map_update {
    my $mapid = shift;
    my $selements_ref = shift;
    $json = {
        jsonrpc => '2.0',
        method  => 'map.update',
        params  => {
            selements => [@{$selements_ref}],
            sysmapid  => $mapid,
        },
        id   => $id++,
        auth => $authID,
    };

    if ( $debug > 0 ) {
        print "About to map.update thisn:";
        print Dumper $json;
    }

    $response = $client->call( $url, $json );

    if ( $debug > 0 ) {
        print Dumper $response;
    }

    # Check if response was successful
    if ( !$response->content->{'result'} ) {
        logout();
        die "map.update failedn";
    }
    return;
}

И сразу добавим скрипт в cron (лучше всего под пользователем zabbix) на машине с Zabbix Server, одного раза в сутки может оказаться вполне достаточно.

* 1 * * * /usr/local/bin/zabbix_syslog_create_urls.pl

Также не забудем сделать файл исполняемым:

chmod +x /usr/local/bin/zabbix_syslog_create_urls.pl

Готово!

Итого

Заббикс много чего умеет «из коробки». Однако, если нет того, что нужно Вам — отчаиваться рано. Zabbix API, а также zabbix_sender, подключаемые модули, UserParameter — все эти инструменты к ваши услугам, чтобы расширить возможности системы.

Автор: wabbit

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js