Предистория. Есть радиооборудование, которое опрашивается по SNMP. Положительный результат запроса приходит только при наличии зарегистрированного клиента или канала. При отсутствии регистрации (выключили клиента, плохие условия приема и т.п.) приходит ответ что запрос не поддерживается и zabbix помечает "Элемент данных" как "Неподдерживаемый" и следующий рас его опросит уже по времени из глобальных настроек. Можно сделать так, что бы опрос велся в любом случае по графику из настроек "Элемента данных"?
Ad Widget
Collapse
Подскажите, можно ли отключить для элемента данных проверку на "поддерживаемость"?
Collapse
X
-
Tags: None
-
Вариант решения для версии 3.4. Делаете тип вашего айтема text или character. Для него делаете зависимый айтем числового типа с регуляркой в препроцессинге, извлекающей число, если основной айтем его получает. Т.о., основной айтем никогда не станет неподдерживаемым, т.к. он текстовый и не обидится на сообщение об ошибке. Зависимый в этом случае будет становиться неподдерживаемым, но будет восстанавливаться сразу при получении основным числа, а не по времени из глобальных настроек. -
Это не решение, от слова совсем. Надо учитывать что
1) ваш зависимый элемент данных не будет возвращать "тоже значение" для COUNTER, и как следствие элемент данных delta не упадет в ноль, а превратится в тыкву
2) интервалы "восстановления" неподдерживаемых элементов данных снижать до нескольких минут нельзя, если общее число собираемых данных достаточно велико, а восстановление через 15 минут элементов данных для описываемой ситуации никого не устроит
По вопросу автора. Есть две ситуации когда элемент данных может стать недоступен, вы не указали какая у вас
1) SNMP OID пропадают из snmp агента, при опросе он вернет что "такой OID не найден". Это самая сложная ситуация, решить ее средствами zabbix невозможно в принципе, придется сдорово переписывать SNMP пуллер. Я решаю это ситуацию с помощью проксирования snmp. Поднимается snmpd (net-snmp), в конфигурации прописываются что и откуда проксировать, затем пишем небольшой скрипт, который цепляется к этой проксе как agentx, и этот скрипт подменяет поведение snmp агента для определенных OID
2) Агент дает ошибку, или просто не отвечает. Это так же происходит если оборудование занято чем то другим и просто скипает обработку входящих snmp запросов. Это можно решить, например, вот так.
P.S. пример agentx
Я бы переписал это, для начала не стоит использовать NetSNMP для запроса значения с snmp агента, реализация модуля очень кривая, приходится в частности пересоздавать объект/сокет на каждый запрос, иначе это поделие тупо виснет в недрах net-snmp, возможно стоит просто использовать Net::SNMP, а от NetSNMP использовать только реализацию agentx.Code:#!/usr/bin/perl use feature 'switch'; use strict; use warnings; use Getopt::Long qw( :config no_posix_default no_ignore_case bundling_override require_order ); use POSIX qw( setsid ); use Unix::Syslog qw( :subs :macros ); use NetSNMP::OID; use NetSNMP::agent; use NetSNMP::ASN qw( ASN_COUNTER ); use NetSNMP::default_store (':all'); use NetSNMP::agent::default_store; use SNMP; $SNMP::auto_init_mib = 0; $SNMP::use_long_names = 1; $SNMP::use_numeric = 1; netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIBDIRS, '/'); netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_READ_CONFIGS, 1); netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1); netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SNMPVERSION, 129); netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS, 1); my $agent = undef; my $running = 1; sub shutdown (); sub daemonize (); sub syserrors (;$); sub setstate ($$;@); sub usage (;$@); # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ my %opt = ( ident => 'agentx-fake-counter', pidfile => '/var/run/agentx-fake-counter.pid', master => '/var/agentx/master', nmsHost => '172.17.11.1', nmsCommunity => 'public' ); GetOptions( \%opt, 'ident|n=s', 'pidfile|p=s', 'master|m=s', 'oid|o=s', 'host|h=s', 'community|c=s', 'debug|d' ) or usage(); daemonize() unless $opt{debug}; my $rootOID = new NetSNMP::OID($opt{oid}) || usage "Can't parse OID:%s", $opt{oid}; my %cache = (); syslog LOG_INFO, "Start OID %s host %s", $rootOID, $opt{host}; setstate $rootOID, ""; $SIG{'INT'} = \&shutdown; $SIG{'QUIT'} = \&shutdown; $SIG{'TERM'} = \&shutdown; netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCKET, $opt{master}); $agent = new NetSNMP::agent('Name' => $opt{ident}, 'AgentX' => 1); $agent->register($opt{ident}, $rootOID, \&agentxHandler); NetSNMP::agent::snmp_enable_syslog_ident($opt{ident}, LOG_LOCAL0) unless $opt{debug}; my $counter = 0; while ($running) { $agent->agent_check_and_process(1); setstate $rootOID, "processed %u requests", $counter; } $agent->shutdown(); unlink $opt{pidfile}; # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ############################################################################################ # function agentxHandler() # parameters: # $handler # $registration_info object # $request_info object # $requests object # return # none # # The handler subroutine will be called when a SNMP request received by # the agent for anything below the registered OID. # sub agentxHandler { my ($handler, $registration_info, $request_info, $requests) = @_; my ($request, $oid, $index, $sess, $vb, $value) = (); for ( $request = $requests; $request; $request = $request->next() ) { $oid = $request->getOID(); $index = ($oid->to_array())[$oid->length() - 1] if $oid > $rootOID; if ( defined $index and $rootOID + $index == $oid or $rootOID == $oid ) { $sess = new SNMP::Session( DestHost => $opt{host}, Community => $opt{community}, Version => 2, Retries => 0, Timeout => 1000000 ); $vb = new SNMP::Varbind([$rootOID, $index]); if ( $request_info->getMode() == MODE_GET ) { $value = $sess->get($vb); if ( $sess->{ErrorNum} or $vb->type =~ /^NOSUCH/i ) { if ( exists $cache{$oid} ) { $request->setValue(ASN_COUNTER, $cache{$oid}); } elsif ( $sess->{ErrorNum} ) { $request->setError($request_info, SNMP_ERR_GENERR); } next; } } elsif ( $request_info->getMode() == MODE_GETNEXT ) { $value = $sess->getnext($vb); next if $sess->{ErrorNum} or $vb->type =~ /^NOSUCH/i; $oid = new NetSNMP::OID( $vb->name ); next unless $rootOID + ($oid->to_array())[$oid->length() - 1] == $oid or $rootOID == $oid; $request->setOID($oid); } $cache{$oid} = $value; $request->setValue(ASN_COUNTER, $value); } else { $request->setError($request_info, SNMP_ERR_NOSUCHNAME); syslog LOG_ERR, "Bad request OID:%s", $oid; } $counter++; } } ############################################################################################ # function shutdown() # parameters: none # return: none # sub shutdown () { $running = 0; syslog LOG_WARNING, "Got signal. Exiting."; } ############################################################################################ # function daemonize() # parameters: none # return: none # $SIG{CHLD} = 'IGNORE'; sub daemonize () { chdir '/' or usage "Can't chdir to /: $!"; open(STDIN, '/dev/null') or usage "Can't read /dev/null: $!"; open(STDOUT, '>> /dev/null') or usage "Can't write to /dev/null: $!"; defined(my $pid = fork) or usage "Can't fork: $!"; if ($pid) { # parent open(PID, "> $opt{pidfile}") or usage "Couldn't open %s for writing: $!", $opt{pidfile}; print PID "$pid\n" or usage "Couldn't write pid to %s: $!", $opt{pidfile}; close(PID) or usage "Couldn't close %s: $!", $opt{pidfile}; exit; } # child setsid() or usage "can't start a new session: $!"; close(STDIN) or usage "Can't close STDIN: $!"; close(STDOUT) or usage "Can't close STDOUT: $!"; close(STDERR) or usage "Can't close STDERR: $!"; openlog $opt{ident}, LOG_PID, LOG_LOCAL0; } sub setstate ($$;@) { $0 = sprintf("%s: %s [%s]", $opt{ident}, shift, sprintf(shift, @_)); } sub usage (;$@) { my ($msg, @params) = @_; print STDERR sprintf($msg, @params) . "\n" if $msg; print STDERR "Who are you? Goodbye!\n"; exit 1; }Comment
-
Преобразования типа simple change или change per second в условиях задачи не обсуждались, но ваша идея насчет тыквы заинтриговала. Проверил, превращения не получилось. Кстати, регулярку в препроцессинг можно не ставить, и без нее работает.Это не решение, от слова совсем. Надо учитывать что
1) ваш зависимый элемент данных не будет возвращать "тоже значение" для COUNTER, и как следствие элемент данных delta не упадет в ноль, а превратится в тыкву
2) интервалы "восстановления" неподдерживаемых элементов данных снижать до нескольких минут нельзя, если общее число собираемых данных достаточно велико, а восстановление через 15 минут элементов данных для описываемой ситуации никого не устроит
Что касается изменения глобальной настройки Refresh unsupported items, то никто этого и не предлагал. На зависимые айтемы она не влияет.
Comment
-
В unsupported у вас уйдет элемент данных типа SNMP, именно об этом был задан вопрос, и этот элемент данных у вас будет основным.
Я без понятия что вы проверяли, но как то слабо верится что зависимый элемент данных в ситуации когда основной ушел в unsupported, продолжит вычисляться и что то сохранять в бд.
И это уже не говоря о том что в ситуации когда SNMP данные по какой то причине отсутствуют (я писал об этом несколько лет назад в теме на которую сослался выше) может требоваться совершенно разная реакция, например, если это уровни сигналов то вероятнее я захочу сохранять что то вроде -10 dB, в не получать "разрыв графика" на 15/30/45/etc минут. Есть и более "странные", с точки зрения реализации, snmp агенты, как пример местоположении (gps) ушедшего в оффлайн устройства snmp agent центрального узла может вернуть "нулевое", и в такой ситуации у zabbix просто не существует механизма верификации, в базу запишутся нули. По идее препроцессинг должен решить эти проблемы, но пока там недостаточно функционала.
Comment
-
Видимо, мы с вами по-разному смотрим на задачу. Я вижу задачу так, как она сформулирована: есть некий собираемый с заданным интервалом айтем, который иногда вместо числа получает текст в виде сообщения об ошибке. Надо сделать так, чтобы, став неподдерживаемым, он восстановился раньше времени, указанного в Refresh unsupported items. Неважно, SNMP это, Zabbix agent или ODBC. Вы же рассказываете о разнообразных проблемах SNMP мониторинга.Comment
-
Нет никакого "текста". Речь идет про штатное поведение SNMP агента, которое обязан обработать код пулера, и он это делает, результатом будет перевод элемента данных zabbix в состояние unsupported, и не важно какой тип данных выбран для вашего SNMP элемента данных.
Смотрите код в src/zabbix_server/poller/checks_snmp.c
Comment
Comment