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

от автора

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

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

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

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

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

How to

Большими мазками архитектура решения выглядит вот так:

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
Тип Zabbix траппер
Ключ syslog Важно, чтобы было именно такое имя (для дальнейшей корректной работы Zabbix API)
Тип информации Журнал(лог)
Формат времени в журнале(логе) yyyyxMMxddxhhxmmxssxxxxxx Маска для правильного определения даты по формату в RFC5424

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

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.cfg\n"; my $user     = $Config{'user'} || die "API user is missing in zabbix_syslog.cfg\n"; my $password = $Config{'password'} || die "API user password is missing in zabbix_syslog.cfg\n"; my $server = $Config{'server'} || die "server hostname is missing in zabbix_syslog.cfg\n"; my $zabbix_sender = $Config{'zabbix_sender'} || '/usr/local/bin/zabbix_sender';  die "Problems with zabbix_sender binary: $ERRNO\n"   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 argument\n";  #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 continue\n"; }  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 failed\n" 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 failed\n" 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 failed\n";     }      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 failed\n";     }      #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 failed\n";     }     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 классифицируются при помощи атрибута 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-сообщениях. В условиях укажем, что имя триггера содержит [SYSLOG], и что отправлять сообщение нужно через электронную почту.

В итоге, каждый раз, когда в syslog упадет сообщение высокой важности, мы будем получать сообщение вида:

И кстати, наш шаблон с триггерами по критичности аварий уже готов:

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-сообщениями — контекстный переход с карты сети.


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

Но скорее руки отсохнут кликать по мышке, либо умом тронешься. Лучше вновь обратимся к 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.cfg\n"; my $user     = $Config{'user'} || die "API user is missing in zabbix_syslog.cfg\n"; my $password = $Config{'password'}   || die "API user password is missing in zabbix_syslog.cfg\n"; my $server = $Config{'server'}   || die "server hostname is missing in zabbix_syslog.cfg\n";  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 failed\n";     }      #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 failed\n" 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 failed\n";     }      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 failed\n" 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 failed\n";     }     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 this\n:";         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 failed\n";     }     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 — все эти инструменты к ваши услугам, чтобы расширить возможности системы.

ссылка на оригинал статьи http://habrahabr.ru/post/252915/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *