Ad Widget
Collapse
Расширяем snmp lld скриптами
Collapse
X
-
Доброго времени суток!
Все вроде шикарно работает за исключением одного:
При обнаружении в логах zabbix такая ошибка
Кто нибудь сталкивался с подобным?Code:14254:20131205:191135.567 item [xxxxxx:cisco_ifindex.pl[{HOST.CONN},{$SNMP_PORT},{$SNMP_COMMUNITY},CI1]] became not supported: timeout while executing a shell script 14254:20131205:191140.571 item [xxxxxx:cisco_ifindex.pl[{HOST.CONN},{$SNMP_PORT},{$SNMP_COMMUNITY},CI3]] became not supported: timeout while executing a shell scriptComment
-
Переписал скрипт на bash, может кому будет полезен, принцип работы идентичный, переменные чуть отличаются, кому нужно правим в глобальных регекспах либо скрипте. Сделал максимально простым (не люблю перл), вместо AdminStatus используется OperStatus, так как мониторю только активные интерфейсы.
Если кому будет интересна данная модификация, выложу шаблоны.Attached FilesComment
-
В таком лучше не признаваться, профи обязан быть всеядным.
Вы действительно считаете что сотня форков (snmp*, sed, grep, awk, etc) и куча дисковых операций с временными файлами это лучше чем perl, который есть в любом "юниксе" и перловые модули, которые есть часть дистрибутива netsnmp? Я понимаю желание переписать на питоне/рельсе/php/etc, но на bash, на мой взгляд, несколько странное решение
Comment
-
А что стыдного признаться в предпочтениях, ну не нравится мне его синтаксис, свой велосипед написать 5 минут, а разобраться в чужом пару часов. Тащить перл на сервер, следить за его модулями, версиями и зависимостями, ну не знаю, если он еще даля чегото используется, то нужен а так обошелся стандартными возможностями. Дисковые операции, да без разницы tmp в оперативе и по таймеру отрабатывает быстрее. Возможно позже перепишу на php, но пока меня устраивает bash (даже если быть точнее sh, так как специфичного для bash там ничего нет). sed и awk есть на любом сервере и как по мне вполне достаточны, тут дело скорее предпочтений.В таком лучше не признаваться, профи обязан быть всеядным.
Вы действительно считаете что сотня форков (snmp*, sed, grep, awk, etc) и куча дисковых операций с временными файлами это лучше чем perl, который есть в любом "юниксе" и перловые модули, которые есть часть дистрибутива netsnmp? Я понимаю желание переписать на питоне/рельсе/php/etc, но на bash, на мой взгляд, несколько странное решение
Comment
-
А не могли бы Вы выложить свой вариант на Python? А то у меня с программированием всё очень плохо, а на python несколько скриптов уже написал, хоть примерно понимаю что это
ps в принципе уже написал - оказывается я что-то подобное уже делал в прошлых скриптах, но всё-равно интересно как подобные задачи решаютсяLast edited by Zero_Full; 20-01-2014, 14:33.Comment
-
Добрый день!
Встала задача, снимать определенную статистику с устройств Axerra,
в процессе решения, пришлось разбираться с perl'ом. Я старался сделать
код максимально читабельным и простым. За основу были взят скрипт
Jimson'а, за что ему огромное спасибо и мне на пальцах объяснял
и показывал работу скрипта, снимающего температуру и состояние
вентиляторов dima_dm, за что ему тоже, не менее огромное спасибо.
Я решил немного расширить задачу и, поскольку изначальный набор
mib'ов с которых будут собираться данные был не известен, пришлось
сделать поддержку конфигурационного файла. Опция --hack нужна для
определения количества интерфейсов на устройстве, ибо, при snmp
запросе нужного mib'а (axnIfNumber)- возвращается неверное значение.
Под заббиксом скрипт работает (при вызове я использую "длинные" ключи, а dima_dm на меня за это ругается
), но (работоспособность с snmp v3 не проверялась), так как нет устройств с snmpv3.
Возможно, кому-то он будет полезен. Пожелания по оптимизации и увеличению быстродействия крайне приветствуются.
P.S: Исправленая версия, так как неверно понял задачу и теперь
несколько переменных выводятся в одном json формате:
Плюс, json проходит проверку на валидность.# ./axerra_ifmib.pl --hack --host xmow265 --version 2c --community public --conffile /var/lib/zabbixsrv/externalscripts/data.txt
{"data":[
{"{#IFINDEX}":"8","{#AXNIFDESCR}":"Circuit Emulation Service Pseudo-Wire","{#AXNIFALIAS}":"0012121_Globex_Hachat_","{# AXNIFTYPE}":"6","{#AXNIFSPEED}":"2048000","{#AXNIF NAME}":"ces-pw io/1/1"}
,{"{#IFINDEX}":"4","{#AXNIFDESCR}":"Ethernet Interface","{#AXNIFALIAS}":"","{#AXNIFTYPE}":"9"," {#AXNIFSPEED}":"10000000","{#AXNIFNAME}":"ethp ni/2"}
,{"{#IFINDEX}":"3","{#AXNIFDESCR}":"Ethernet Interface","{#AXNIFALIAS}":"To_","{#AXNIFTYPE}":"9 ","{#AXNIFSPEED}":"100000000","{#AXNIFNAME}":" ethp ni/1"}
,{"{#IFINDEX}":"9","{#AXNIFDESCR}":"Tunnel","{#AXN IFALIAS}":"XMOW256-XMOW2","{#AXNIFTYPE}":"12","{#AXNIFSPEED}":"211200 0","{#AXNIFNAME}":"tunnel cpt.2"}
,{"{#IFINDEX}":"2","{#AXNIFDESCR}":"E1T1 Interface","{#AXNIFALIAS}":"0012121_Globex_Hachat" ,"{#AXNIFTYPE}":"1","{#AXNIFSPEED}":"2048000","{#A XNIFNAME}":"e1t1 io/1"}
,{"{#IFINDEX}":"5","{#AXNIFDESCR}":"Ethernet Interface","{#AXNIFALIAS}":"","{#AXNIFTYPE}":"9"," {#AXNIFSPEED}":"10000000","{#AXNIFNAME}":"ethp ni/3"}
]}
Code:#!/usr/bin/perl # This script has been written under the influence # of two small scripts which had been taken from Zabbix # forum, and carefully studied. One of them read the # information about condition of system fans on Cisco # equipment and put variables into Zabbix's template. # And another had several mibs, but it contained it inside # their own body. Present script absorbed some part of # code those two scripts but it expands the whole idea, # and can read information from configuration file. # Configuration file defined by using key -f or --file # as an argument for this script. # # Configuration file format is trivial: # # # ethp # axnethInOctets = 1.3.6.1.4.1.10117.1.3.2.20.1.1.20 # "#" signs treated as a comment. # I want to say "thank you very much" to Dmitry Maximov # and Michael Pruzhanskiy, they both helped me with debugging. # Their help and advices has been priceless. And also # I want to say "thank you" to Jimson from Zabbix # forum. # Script requires perl-Net-SNMP package, if you are using # CentOS6/RHEL6, or libnet-snmp-perl package if you are # using Debian. use strict; use warnings; use File::Basename; use Getopt::Long; use POSIX qw(strftime); use SNMP; use utf8; our $VERSION = '0.0.21'; my $scriptname = basename ("$0"); # define snmp v2/v3 arguments for our script my $host = undef; my $port = undef; my $version = undef; my $community = undef; my $conffile = undef; my $secname = undef; my $seclevel = undef; my $secengineid = undef; my $contextengineid = undef; my $context = undef; my $authproto = undef; my $authpass = undef; my $privproto = undef my $privpass = undef; my $help = undef; my $hack = undef; my ($value, $var); # our data in configuration file my %user_preferences; # hash for our definition in conffile # Logging to STDERR and exit sub error { printf STDERR ("%6u:%s.000 $host $community %s failed: %s\n", $$, strftime("%Y%m%d:%H%M%S", localtime()), @_); exit 1; } # Programm usage sub usage { printf ("Usage: $scriptname <version> <community> <host>\n"); printf ("\t", "Options:\n"); printf (" --help\t Display this help message.\n"); printf ("\t --hack\t Ugly hack for Axerra devices.\n"); printf ("\t -h, --host\t Hostname or IP address of the SNMP agent you want to talk to.\n"); printf ("\t -v, --version\t SNMP version to use.\n"); printf ("\t -c, --community\t For SNMPv1 and SNMPv2c, the clear-text community name to use.\n"); printf ("\t -f, --conffile\t Configuration file.\n"); printf ("\t --secname\t The SNMPv3 security name to use (most for SNMPv3 with USM).\n"); printf ("\t --seclevel\t The SNMPv3 security level to use [noAuthNoPriv, authNoPriv, authPriv].\n"); printf ("\t --secengineid\t The SNMPv3 security engineID to use (if the snmpv3 security model needs it; for example USM).\n"); printf ("\t --contextengineid\t The SNMPv3 context engineID to use.\n"); printf ("\t --context\t The SNMPv3 context name to use.\n"); printf ("\t --authproto\t The SNMPv3/USM authentication protocol to use [MD5, SHA].\n"); printf ("\t --authpass\t The SNMPv3/USM authentication passphrase to use.\n"); printf ("\t --privproto\t The SNMPv3/USM privacy protocol to use [DES, AES].\n"); printf ("\t --privpass\t The SNMPv3/USM privacy passphrase to use.\n"); } # Get amount of interfaces sub int_count { my $sess = pop @_; my $int_count; if (defined ($hack) && ($version eq "2c")) { $int_count = `/usr/bin/snmpwalk -v $version -c $community $host 1.3.6.1.4.1.10117.1.3.1.1.1.3 | /usr/bin/wc -l`; } elsif (defined ($hack) && ($version eq "3")) { $int_count = `/usr/bin/snmpwalk -v $version -a $authproto -A $authpass -x $privproto -X $privpass -l $seclevel \ $host 1.3.6.1.4.1.10117.1.3.1.1.1.3 | /usr/bin/wc -l`; } else { $int_count = $sess->get('ifNumber'); } return ($int_count); } # reading defined configuration file sub read_conf_file { open (CONFIG, "<", $conffile) || die "Can not open file: $!"; while (<CONFIG>) { chomp ($_); # Убрать перевод строки $_ =~ s/#.*//; # Убрать комментарии $_ =~ s/^\s+//; # Убрать начальные пропуски $_ =~ s/\s+$//; # Убрать конечные пропуски if (! length $_) { next; } ($var, $value) = split(/\s*=\s*/, $_, 2); $user_preferences{$var} = $value; } close(CONFIG); } sub get_data { my $sess = pop @_; my $interface_count = pop @_; my %user_preferences = @_; my %output = (); for my $hash (sort keys %user_preferences) { my ($bulkwalk_data) = $sess->bulkwalk(0, $interface_count, [[$user_preferences{$hash}]]); error("bulkwalk [$hash]", $sess->{ErrorStr}) if ($sess->{ErrorNum}); my $count = @$bulkwalk_data; if (! $count) { next; } my %json = (); foreach (@$bulkwalk_data) { $json{$_->iid}={ uc($hash) => $_->val}; } # Save snmp data to %output while (my ($index, $data) = each %json) { while ( my ($macro, $val) = each %$data) { push @{ $output{$index}{$macro} }, $val; } } } # Print data from %output in valid JSON format my $flag; print '{"data":[', "\n"; while (my ($index, $data) = each %output) { if (! $flag) { print '{"{#IFINDEX}":"', $index, '"'; } else { print ',{"{#IFINDEX}":"', $index, '"'; } my @tmp_macro_vals; while ( my ($macro, $val) = each %$data ) { push (@tmp_macro_vals, ',', map { '"{#'. $macro . '}":"'. $_. '"' } @$val); } print @tmp_macro_vals; $flag++; print "}\n"; } print "]}\n"; exit 0; } if (! @ARGV) { usage; exit 255; } GetOptions ( 'h|host=s' => \$host, 'p|port:s' => \$port, 'v|version=s' => \$version, 'c|community:s' => \$community, 'f|conffile:s' => \$conffile, 'secname=s' => \$secname, 'seclevel:s' => \$seclevel, 'secengineid:s' => \$secengineid, 'contextengineid:s'=> \$contextengineid, 'context:s' => \$context, 'authproto:s' => \$authproto, 'authpass:s' => \$authpass, 'privproto:s' => \$privproto, 'privpass:s' => \$privpass, 'help:s' => \$help, 'hack:s' => \$hack) || die (&usage); if (defined($help)) { &usage; exit 255; } my $sess = new SNMP::Session( DestHost => "$host", Community => "$community", UseNumeric => 1, NonIncreasing => 1, UseLongNames => 1, Version => "$version", Timeout => 8 * 1000000, Retries => 1 ); if (($version eq "2c") && (! $community)) { print ("You forgot to define community: $community and/or snmp version: $version\n"); exit 255; } my $interface_count = int_count($sess); read_conf_file; get_data (%user_preferences, $interface_count, $sess); if (($version eq "3") && (! $authproto) && (! $authpass) && (! $privproto) && (! $privpass) && (! $seclevel)) { print ("You forgot to define at least one option from the following: authproto: $authproto, authpass: $authpass\n"); print ("privproto: $privproto, privpass: $privpass, seclevel: $seclevel \n"); exit 255; } else { $sess = new SNMP::Session( DestHost => "$host", Community => "$community", UseNumeric => 1, NonIncreasing => 1, UseLongNames => 1, Version => "$version", Timeout => 8 * 1000000, Retries => 1, SecLevel => "$seclevel", AuthProto => "$authproto", AuthPass => "$authpass", PrivProto => "$privproto", PrivPass => "$privpass" ); my $interface_count = int_count($sess); read_conf_file; get_data (%user_preferences, $interface_count, $sess); }Comment
-
Jimson, подскажите, вы уже переехали на 2.2 версию?
У меня тут маленькая проблема: открываю узел к которому привязаны шаблоны автообнаружения, с правой стороны в колонке ошибка висит напротив правила обнаружения: Value should be a JSON object
складывается чувство что что-то поменяли в json парсинге на новой версии.Comment
-
Проверьте полученные данные через http://jsonlint.com/ или другой онлайн валидатор, найдете ошибку. Проблем в 2.2. нету, хотя пользуюсь собственным скриптом, а не от топикстартера.Jimson, подскажите, вы уже переехали на 2.2 версию?
У меня тут маленькая проблема: открываю узел к которому привязаны шаблоны автообнаружения, с правой стороны в колонке ошибка висит напротив правила обнаружения: Value should be a JSON object
складывается чувство что что-то поменяли в json парсинге на новой версии.Comment
-
Еще нет. Уже много раз тут был вопрос на тему JSON: в 2.2 добавили верификацию из-за чего JSON с лишними запятыми (после последней строки) считается не валидным.Jimson, подскажите, вы уже переехали на 2.2 версию?
У меня тут маленькая проблема: открываю узел к которому привязаны шаблоны автообнаружения, с правой стороны в колонке ошибка висит напротив правила обнаружения: Value should be a JSON object
складывается чувство что что-то поменяли в json парсинге на новой версии.
Самый простой вариант сделать так:
#
# Output in JSON format
#
use JSON;
my ($index, $hash, $macro, $value, @data) ;
while (($index, $hash) = each %json) {
my $h = { '{#IFINDEX}' => $index };
while (($macro, $value) = each %$hash) {
$h->{ "{#$macro}" } = $value;
}
push @data, $h;
}
print encode_json { data => \@data };
вроде работаетЕстественно надо поставить перловую библиотеку JSON, они маленькая и без зависимостей http://search.cpan.org/~makamaka/JSON-2.90/Code:msk-be-srv-vk1[jimson]:~ $ cat x.pl use JSON; %json = ( 1 => { NAME => "xx", OTHER => "yy" }, 5 => { NAME => "xx", OTHER => "yy" }, ); my ($index, $hash, $macro, $value, @data) ; while (($index, $hash) = each %json) { my $h = { '{#IFINDEX}' => $index }; while (($macro, $value) = each %$hash) { $h->{ "{#$macro}" } = $value; } push @data, $h; } print encode_json { data => \@data }; print "\n"; msk-be-srv-vk1[jimson]:~ $ perl x.pl {"data":[{"{#IFINDEX}":"1","{#NAME}":"xx","{#OTHER}":"yy"},{"{#IFINDEX}":"5","{#NAME}":"xx","{#OTHER}":"yy"}]} msk-be-srv-vk1[jimson]:~ $
в FreeBSD: /usr/ports/converters/p5-JSON/
в дебианах всяких наверно libjson-perlComment
-
да, сработало, спасибо, только маленький вопрос:
а как теперь вывод сделать читабельным? сейчас получается все в одну строку лепится, но уже в чистом json.Comment
-
Так это же лучше, оно меньше памяти в буферах занимает.
Но включить можно, в документации на CPAN написано как это делать, надо вначале создать объект $j = JSON->new(), затем включить эту "фичу" $j->pretty(1), а затем уже сделать вывод $jsontext = $j->utf8->encode($hashref), можно и одной строкой это сделать вроде как:
print JSON->new()->pretty(1)->utf8->encode->( { data => \@data } );
Можно и включить только нужные "пробелы", метод pretty() эквивалентен $jsonobj->indent->space_before->space_after, эксперементируйте.Last edited by Jimson; 21-02-2014, 09:03.Comment
-
[QUOTE=logicall;140403]Всем добрый день!
Решил попробовать lld, предложенный Jimson, и столкнулся с проблемой
В логе zabbix сыпятся ошибки
Добрый день всем.Code:Can't call method "bulkwalk" on an undefined value at /usr/local/etc/externalscripts/cisco_ifmib.pl line 75
Тоже столкнулась с данной проблемой, но ответа так и не нашла.
Думаю это может кому-нить пригодиться.
Данная ошибка означает что переменная $sess не создана.
В моём случае данная ошибка вылезала из-за того что скрипт отрабатываемый в заббиксе нивкакую не мог понять DestHost с указанием порта, хотя в консоли отрабатывал корректно.
Возможно это происходит и у других кто пытается запустить скрипт и получает данную ошибку.Comment
Comment