Ad Widget

Collapse

Расширяем snmp lld скриптами

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • logicall
    Junior Member
    • Mar 2009
    • 14

    #76
    Originally posted by logicall
    Всем привет!
    Кто-нибудь сталкивался при использовании lld через внешние проверки с ошибкой "Cannot create item: item with the same key "InOctets.[{#IFDESCR}]" already exists."?
    Я уже и хост удалял и шаблон... Переименовывал ключ у элемента данных... Ничего не помогает...
    Может кто знает как победить?
    PS
    Я прямо в базе искал такой ключ - нету его в таблице item_discovery. Хотя сами итемы есть.. Но key в них пустой
    Разобрался....
    Я json возвращал не {#IFDESCR}, а #IFDESCR. Фигурные скобки пропустил

    Comment

    • denis005
      Junior Member
      • Dec 2013
      • 4

      #77
      Доброго времени суток, уважаемые!


      Jimson - Спасибо большое за топик, и скрипт.

      Настроил под себя, сейчас жду пока начнет сканиться, надеюсь проблем не возникнет!

      Comment

      • denis005
        Junior Member
        • Dec 2013
        • 4

        #78
        Доброго времени суток!

        Все вроде шикарно работает за исключением одного:

        При обнаружении в логах 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 script
        Кто нибудь сталкивался с подобным?

        Comment

        • Rico-X
          Junior Member
          • Jun 2012
          • 22

          #79
          Переписал скрипт на bash, может кому будет полезен, принцип работы идентичный, переменные чуть отличаются, кому нужно правим в глобальных регекспах либо скрипте. Сделал максимально простым (не люблю перл), вместо AdminStatus используется OperStatus, так как мониторю только активные интерфейсы.
          Если кому будет интересна данная модификация, выложу шаблоны.
          Attached Files

          Comment

          • Jimson
            Senior Member
            • Jan 2008
            • 1327

            #80
            Originally posted by denis005
            Кто нибудь сталкивался с подобным?
            Таймаут какой стоит в zabbix_server.conf ?

            Comment

            • Jimson
              Senior Member
              • Jan 2008
              • 1327

              #81
              Originally posted by Rico-X
              (не люблю перл)
              В таком лучше не признаваться, профи обязан быть всеядным.
              Вы действительно считаете что сотня форков (snmp*, sed, grep, awk, etc) и куча дисковых операций с временными файлами это лучше чем perl, который есть в любом "юниксе" и перловые модули, которые есть часть дистрибутива netsnmp? Я понимаю желание переписать на питоне/рельсе/php/etc, но на bash, на мой взгляд, несколько странное решение

              Comment

              • Rico-X
                Junior Member
                • Jun 2012
                • 22

                #82
                Originally posted by Jimson
                В таком лучше не признаваться, профи обязан быть всеядным.
                Вы действительно считаете что сотня форков (snmp*, sed, grep, awk, etc) и куча дисковых операций с временными файлами это лучше чем perl, который есть в любом "юниксе" и перловые модули, которые есть часть дистрибутива netsnmp? Я понимаю желание переписать на питоне/рельсе/php/etc, но на bash, на мой взгляд, несколько странное решение
                А что стыдного признаться в предпочтениях, ну не нравится мне его синтаксис, свой велосипед написать 5 минут, а разобраться в чужом пару часов. Тащить перл на сервер, следить за его модулями, версиями и зависимостями, ну не знаю, если он еще даля чегото используется, то нужен а так обошелся стандартными возможностями. Дисковые операции, да без разницы tmp в оперативе и по таймеру отрабатывает быстрее. Возможно позже перепишу на php, но пока меня устраивает bash (даже если быть точнее sh, так как специфичного для bash там ничего нет). sed и awk есть на любом сервере и как по мне вполне достаточны, тут дело скорее предпочтений.

                Comment

                • Zero_Full
                  Junior Member
                  • Oct 2011
                  • 3

                  #83
                  Originally posted by logicall
                  Разобрался....
                  Я json возвращал не {#IFDESCR}, а #IFDESCR. Фигурные скобки пропустил
                  А не могли бы Вы выложить свой вариант на Python? А то у меня с программированием всё очень плохо, а на python несколько скриптов уже написал, хоть примерно понимаю что это

                  ps в принципе уже написал - оказывается я что-то подобное уже делал в прошлых скриптах, но всё-равно интересно как подобные задачи решаются
                  Last edited by Zero_Full; 20-01-2014, 14:33.

                  Comment

                  • andrewclark
                    Junior Member
                    • Jan 2014
                    • 1

                    #84
                    Добрый день!
                    Встала задача, снимать определенную статистику с устройств Axerra,
                    в процессе решения, пришлось разбираться с perl'ом. Я старался сделать
                    код максимально читабельным и простым. За основу были взят скрипт
                    Jimson'а, за что ему огромное спасибо и мне на пальцах объяснял
                    и показывал работу скрипта, снимающего температуру и состояние
                    вентиляторов dima_dm, за что ему тоже, не менее огромное спасибо.
                    Я решил немного расширить задачу и, поскольку изначальный набор
                    mib'ов с которых будут собираться данные был не известен, пришлось
                    сделать поддержку конфигурационного файла. Опция --hack нужна для
                    определения количества интерфейсов на устройстве, ибо, при snmp
                    запросе нужного mib'а (axnIfNumber)- возвращается неверное значение.

                    Под заббиксом скрипт работает (при вызове я использую "длинные" ключи, а dima_dm на меня за это ругается ), но (работоспособность с snmp v3 не проверялась), так как нет устройств с snmpv3.
                    Возможно, кому-то он будет полезен. Пожелания по оптимизации и увеличению быстродействия крайне приветствуются.

                    P.S: Исправленая версия, так как неверно понял задачу и теперь
                    несколько переменных выводятся в одном 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"}
                    ]}
                    Плюс, json проходит проверку на валидность.

                    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);
                    
                    	}
                    Last edited by andrewclark; 19-02-2014, 14:53. Reason: Поправлены ошибки в скрипте

                    Comment

                    • Melanxolik
                      Senior Member
                      • Nov 2009
                      • 174

                      #85
                      Jimson, подскажите, вы уже переехали на 2.2 версию?

                      У меня тут маленькая проблема: открываю узел к которому привязаны шаблоны автообнаружения, с правой стороны в колонке ошибка висит напротив правила обнаружения: Value should be a JSON object
                      складывается чувство что что-то поменяли в json парсинге на новой версии.

                      Comment

                      • Rico-X
                        Junior Member
                        • Jun 2012
                        • 22

                        #86
                        Originally posted by Melanxolik
                        Jimson, подскажите, вы уже переехали на 2.2 версию?

                        У меня тут маленькая проблема: открываю узел к которому привязаны шаблоны автообнаружения, с правой стороны в колонке ошибка висит напротив правила обнаружения: Value should be a JSON object
                        складывается чувство что что-то поменяли в json парсинге на новой версии.
                        Проверьте полученные данные через http://jsonlint.com/ или другой онлайн валидатор, найдете ошибку. Проблем в 2.2. нету, хотя пользуюсь собственным скриптом, а не от топикстартера.

                        Comment

                        • Jimson
                          Senior Member
                          • Jan 2008
                          • 1327

                          #87
                          Originally posted by Melanxolik
                          Jimson, подскажите, вы уже переехали на 2.2 версию?

                          У меня тут маленькая проблема: открываю узел к которому привязаны шаблоны автообнаружения, с правой стороны в колонке ошибка висит напротив правила обнаружения: Value should be a JSON object
                          складывается чувство что что-то поменяли в json парсинге на новой версии.
                          Еще нет. Уже много раз тут был вопрос на тему JSON: в 2.2 добавили верификацию из-за чего 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 };

                          вроде работает
                          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]:~ $
                          Естественно надо поставить перловую библиотеку JSON, они маленькая и без зависимостей http://search.cpan.org/~makamaka/JSON-2.90/
                          в FreeBSD: /usr/ports/converters/p5-JSON/
                          в дебианах всяких наверно libjson-perl

                          Comment

                          • Melanxolik
                            Senior Member
                            • Nov 2009
                            • 174

                            #88
                            да, сработало, спасибо, только маленький вопрос:
                            а как теперь вывод сделать читабельным? сейчас получается все в одну строку лепится, но уже в чистом json.

                            Comment

                            • Jimson
                              Senior Member
                              • Jan 2008
                              • 1327

                              #89
                              Originally posted by Melanxolik
                              да, сработало, спасибо, только маленький вопрос:
                              а как теперь вывод сделать читабельным? сейчас получается все в одну строку лепится, но уже в чистом json.
                              Так это же лучше, оно меньше памяти в буферах занимает.
                              Но включить можно, в документации на 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

                              • annawhite
                                Junior Member
                                • Oct 2013
                                • 12

                                #90
                                [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

                                Working...