Nagios — система моніторингу і деякі саморобні плагіни

Коли я вибирав системи моніторингу, я порівнював кактус, нагиос і забикс. І вибрав нагиос. Зараз моїй історії моніторингу вже десяток років, накопичилося самописних рішень, аналоги частини з яких можна знайти в інтернеті, а частини і немає. Тому вирішив зібрати все в одне місце, нехай лежить. Якщо ви самі щільно багато років використовуєте нагиос, то навряд чи знайдете тут якісь одкровення, але в скарбничку може що і стане в нагоді. А для початківців може виявитися корисним.

Отже, поїхали. Пара говорок — я описую моніторинг з боку nagios, тому як і що налаштовувати на серверах, які треба моніторити — згадую в загальному вигляді. І друге — я не люблю імена mibs, намагаюся використовувати oid, циферки. Якщо за ним шукати в гуглі, то ви знайдете і їх імена, і сусідні мибы. Власне, знати потрібний oid — це 2/3 справи у разі snmp-моніторингу.

В якості мови програмування в даному разі я волію perl — його простіше налагоджувати і переносити між платформами.

Я обов'язково буду наводити приклади плагінів (інакше для чого б я затіяв цю статтю), у тому числі може бути стандартних, тому що вже не пам'ятаю, що йшов в комплекті, що искалось з миру по нитці і допиливалось. Пам'ятаю лише, що писав сам з нуля, там мої копірайти стоять.

Для самостійного огляду дерева oid рекомендую стандартну утиліту snmpwalk. Сам нагиос у мене а) версії 3.x, б) встановлений на FreeBSD, тому шляху часто будуть типові для Free і нетипові для linux.

Моніторинг windows-серверів
Використовуємо банальний вбудований snmp (який є в windows-серверах починаючи з windows 2000). Цей сервіс за замовчуванням не варто, його треба додати, налаштувати community name (snmp пароль) і ip-адреси, з яких можна звертатися до сервісу (за замовчуванням пароль public і дозволений тільки локальний ip). Опис windows mibs можна легко знайти в інеті.

Стандартний плагін check_disk_snmp.pl дозволяє моніторити диски по імені (що важливо, тому що порядок дисків в дереві snmp може міняти після перезавантаження; якщо ми говоримо саме про сервер, який перезавантажують 1-2 рази на рік; за цей час у нього може нарости шар «зовнішніх» — fibrechannel або iscsi — дисків. Букви в них зберігатися після перезавантаження, а от порядок в дереві snmp — не факт). А так само він дозволяє моніторити стан ОЗП — вільно, включена, swap.

Стандартний плагін check_snmp_load.pl дозволяє моніторити навантаження cpu на сервері, а стандартні плагіни check_tcp і check_udp — доступність мережевих портів. Бо для чого ще потрібен сервер, як не для обслуговування мережних запитів!

Опис стандартних oid, на які відгукується windows доступно тут. Там є і CPU, і ОЗУ, і пристрої зберігання даних (в тому числі за типом — CDROM, Floppy, HDD), запущені процеси і встановлені програми.

Моніторинг unix-серверів
Тут теж все просто. Встановлюєте на сервері пакет net-snmp, налаштовуєте snmpd.conf. В останніх версіях там пекло і хаос, я волію (ось такий я консерватор)

стару добру схему snmp v2rocommunity public 127.0.0.1
rocommunity vasik 10.0.9.1 без всякого новомодного жаху, але це на любителя. Перезапускаєте snmpd і треба моніторити.

Вышепомянутый check_disk_snmp.pl вміє моніторити і unix-сервера. Плюс є альтернатива — плагін check_snmp_storage.pl. У мене історично склалося так, що windows-сервера через моніторяться check_disk_snmp.pl, а unix-сервера — через check_snmp_storage.pl. Він використовує ту ж 25 гілку oid і теж дозволяє моніторити дискові розділи по імені (точці монтування). Тому що всім, окрім адміна самого сервера, абсолютно не цікаво, що саме у нього причеплено в точку /data, або /var, або /opt, або /mnt/disk0101019084. Важливо — скільки там місця всього, скільки зайнято, скільки вільно.
Вищезгаданий ж check_snmp_load.pl вміє моніторити cpu на unix-серверах, check_tpc і check_udp — доступність мережевих портів.

Крім того, у нагиоса є корисний плагін check_by_ssh. Суть його в тому, що він встановлює ssh-з'єднання з хостом і запускає там задану програму. Програма повинна відповідати у форматі nagios (код завершення 0 — успішно, 1 — warning, 2 — critical, 3 — unknown) і може виконувати будь-які бажані вам (і адміну того сервера) перевірки.

На поштових серверах буває корисно моніторити стан поштової черги. Для цього можна використовувати check_by_ssh, але так історично склалося, що я використовую розширення snmp (нагадую, у мене стара, обросла черепашками система моніторингу — але це і добре, можна на живих прикладах показати різні способи отримати один і той же результат). Плюс підходу «без ssh» очевидний — сервер моніторингу не має можливості підключитися до досліджуваного сервера по ssh і не створює дірку у безпеці.

Отже, розширюємо snmp. На досліджуваному сервер в snmpd.conf пишемо рядок виду
extend mailq /root/getmailq.sh
, де extend — команда, mailq — назву гілки,

/root/getmailq.sh — виконувана команда.
ls -al /var/spool/mqueue | wc -l

(ці конкретні сервера — freebsd, linux або інших unix розташування черзі може відрізнятися).

На сервері моніторингу

пишемо скрипт (для різноманітності — bash)
#!/usr/bin/bash

# © by Smithson Inc, 2006

SNMP=/usr/bin/snmpget
HOST=$1
PASS=$2
WARN=$3
CRIT=$4

if [ -z $HOST ]; then
echo Usage $0 HOST [SNMPCOMMUNITY [WARN [CRIT]]]
exit 3
fi

if [ -z $PASS ]; then
PASS=public
fi

if [ -z $WARN ]; then
WARN=1000
fi

if [ -z $CRIT ]; then
CRIT=5000
fi

Q=`$SNMP -2c v -c $PASS $HOST NET-SNMP-EXTEND-MIB::nsExtendOutLine.\"mailq\".1 | awk '{ print $4}"


if [ $Q -ge $CRIT ]; then
echo "CRITICAL: mailq is $Q"
exit 2
fi

if [ $Q -ge $WARN ]; then
echo "WARNING: mailq is $Q"
exit 1
fi


Власне магія криється в запиті NET-SNMP-EXTEND-MIB::nsExtendOutLine.\«mailq\».1 — це ми читаємо, що нам віддає скрипт з спостережуваного сервера.

Ну і стандартне для нагиоса опис команди

define command{
command_name check-snmp-mailq
command_line /path-to-scripts/snmp_extend_mailq.sh $HOSTADDRESS$ $ARG1$ $ARG2$ $ARG3$
}

Це хороша альтернатива check_by_ssh з однією обмовкою. snmpd на сервері за замовчуванням працює від рута. А check_by_ssh може працювати від іншого юзера, з меншими повноваженнями. Вирішувати вам.

Тепер про dns. Дуже часто моніторинг dns зводять до банального check_udp!53. Це дуже блаародно, але малоінформативно. Сервер може працювати, але не дозволяти імена. Сервер може працювати і бути кореневим для ваших імен, але реєстрація домену могла протухнуть. Нічого цього ви з перевірки доступності порту не побачите. Тому пара скриптів перевірки ДНС.

Перший скрипт дозволяє моніторити ваш(і) домен(и) і не проспати необхідність їх продовження. Навіть якщо домен вам подовжує провайдер автоматом, проконтролювати цей факт завжди корисно.

check-domaintime.pl
#!/usr/bin/perl
#
# © Smithson Inc, 2013
#
use HTTP::Date;

my $domain = $ARGV[0];
if (!(defined($domain))) { 
print "Usage: $0 domain.name\n\n";
exit(-1);
} 

$DD=`whois $domain | grep paid-till`;
$DAY = 86400;
$WARNING = $ARGV[1] ? $ARGV[1] : 36;
$CRITICAL = $ARGV[2] ? $ARGV[2] : 10;

if ($DD =~ /(\d\d\d\d\.\d\d\.\d\d)/) {
my $dx = str2timestamp($1);
my $dz = time();

print "Whois $domain end date: $1\n";
if ($dz > ($dx-($CRITICAL*$DAY))) { exit(2); } 
if ($dz > ($dx-($WARNING*$DAY))) { exit(1); } 
exit(0);
} else {
print "Error whois answer: $DD\n";
exit(-1);
}


sub str2timestamp {
my $time = shift;
$time =~ s/(\d+)\.(\d+)\.(\d+)/$1-$2-$3/;
my $timenix = str2time( $time );
return $timenix;
}


Використовується він банально

./check-domaintime.pl smithson.ru [warning [critical]]

За замовчуванням 36 днів до закінчення строку реєстрації — warning, 10 днів — critical.

Другий скрипт служить для перевірки працездатності dns-сервера

check_dns.pl
#!/usr/local/bin/perl
#
# © Smithson Inc, 2015
#

#use strict;
use lib "/usr/local/libexec/nagios";
use utils qw($TIMEOUT %ERRORS &print_revision &support);
use vars qw($PROGNAME);
use Getopt::Long;
use Time::gmtime;
use vars qw($opt_V $opt_h $verbose $opt_w $opt_c $opt_H $volname $opt_mode $mode);

$PROGNAME = `basename $0`;

Getopt::Long::Configure('bundling');
GetOptions
("V" => \$opt_V, "version" => \$opt_V,
"h" => \$opt_h, "help" => \$opt_h,
"a=s" => \$opt_addr, "addr=s" => \$opt_addr,
"H=s" => \$opt_H, "hostname=s" => \$opt_H);


if ($opt_V) {
print_revision($PROGNAME,"); #'
exit $ERRORS{'OK'};
}

if ($opt_h) {
print_help();
exit $ERRORS{'OK'};
}

$opt_H = shift unless ($opt_H);
my $host = $1 if ($opt_H =~ m/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+|[a-zA-Z] [a-zA-Z0]+(\.[a-zA-Z] [a-zA-Z0]+)*)$/);
if (!(defined($host))) { print_usage(); exit $ERRORS{'ERROR'}; };

my $addr = 0;
($opt_addr) || ($opt_addr = shift) || ($opt_addr = 'www.slavneft.ru');

$addr = $opt_addr;

$code = $ERRORS{'OK'};

my $look = '/usr/local/bin/nslookup';
my $n = getdns($host, $addr);
print "$n\n";

exit ($code);

# ================================================================
sub getdns {
my $ip = shift $s $ret=";
my $addr = shift;
$s = "$look $addr $ip";

my $s = `$s`;

my @D = split(/\n/, $s);
foreach my $i (@D) {
if ($i =~ /server can.t find/) { $code = $ERRORS{'WARNING'}; }
if ($i =~ /no servers could be reached/) { $code = $ERRORS{'ERROR'}; }
$ret = $ret.' '.$i; 
}

return $ret;
}
# ================================================================
sub print_usage () {
print "Usage: $PROGNAME -H <host> [-a] address\n";
}
# ================================================================
sub print_help () {
print_revision($PROGNAME,");
print "Copyright © Smithson Inc, 2015 \n";
print "\n";
print_usage();
print "\n";
print "<address> Address for conversion to ip \n\n";
support();
};
# ================================================================

Цей скрипт можна використовувати двома способами. Перший — перевірка через ваш сервер доступність потрібних вам адрес і взагалі роботи dns. Наприклад, так:

check-dns.pl ip вашого сервера google.com

Якщо ваш сервер резолвит google.com — то dns на ньому працює. У разі, якщо немає доступу в інет, резолвинг не спрацює, але це ви побачите по інших перевірок (пінги gateway провайдера, пінг того ж 8.8.8.8).

Так само ви можете перевіряти, що резолвятся потрібні вам внутрішні імена (наприклад, AD стає погано, якщо її власний dns не розпізнає імена).

Другий спосіб — перевірка через гарантовано працює dns ваших імен, які повинні бути доступні з інтернету.

check-dns.pl 8.8.8.8 smithson.ru

Якщо відповідь є — ваші імена з інету доступні (із застереженням про доступність Інтернет в даний момент для вашої системи моніторингу).

Моніторинг Netware
Так-так, я знаю, некрофілія фу, але навіть сьогодні у мене з приблизно 200 серверів у системі є 2 (два!) Netware. Обидва в далеких ДО, налаштовані в одна тисяча вісімсот затертому році і з тих пір працюють, працюють і працюють. У одного з uptime сьогодні 834 дні. Це до слова. Тому — моніторинг.

На останній netware 6.5.8 є snmp. Чесно скажу — не знаю, не їв. З версії 4.11 для netware є програмка mrtgext.nlm, яка дозволяє моніторити купу параметрів сервера. Ось її-то зазвичай і використовують для відображення статистики сервера через mrtg або rrdtool, ну і для моніторингу через нагиос вона цілком годиться. До того ж один з цих двох моїх NW має версію 5.1 (гусари, мовчати!).

mrtgext слухає tcp-порт 9999, тому не забудьте поставити його на моніторинг. Оскільки Netware — це насамперед файловий сервер, то нам цікавіше всього, що відбувається з томами. Для це є скриптик:

check_nwvolsize
#! /usr/local/bin/perl 
#
# © Smithson Inc
#
#

use strict;
use lib "/usr/local/libexec/nagios";
use utils qw($TIMEOUT %ERRORS &print_revision &support);
use vars qw($PROGNAME);
use Getopt::Long;
use vars qw($opt_V $opt_h $verbose $opt_w $opt_c $opt_H $volname $opt_prefix $prefix);

$PROGNAME = `basename $0`;

Getopt::Long::Configure('bundling');
GetOptions
("V" => \$opt_V, "version" => \$opt_V,
"h" => \$opt_h, "help" => \$opt_h,
"v=s" => \$volname, "volname" => \$volname,
"w=s" => \$opt_w, "warning=s" => \$opt_w,
"c=s" => \$opt_c, "critical=s" => \$opt_c,
"p=s" => \$opt_prefix, "prefix=s" => \$opt_prefix,
"H=s" => \$opt_H, "hostname=s" => \$opt_H);


if ($opt_V) {
print_revision($PROGNAME,"); #'
exit $ERRORS{'OK'};
}

if ($opt_h) {
print_help();
exit $ERRORS{'OK'};
}

$opt_H = shift unless ($opt_H);
my $host = $1 if ($opt_H =~ m/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+|[a-zA-Z] [a-zA-Z0]+(\.[a-zA-Z] [a-zA-Z0]+)*)$/);
if (!(defined($host))) { print_usage(); exit $ERRORS{'ERROR'}; };

($opt_c) || ($opt_c = shift) || ($opt_c = 92);
my $critical = $1 if ($opt_c =~ /([0-9]+)/);

($opt_w) || ($opt_w = shift) || ($opt_w = 80);
my $warning = $1 if ($opt_w =~ /([0-9]+)/);

($volname) || ($volname = shift) || ($volname = 'SYS');
my $vname = $volname;

my $ppp = $opt_prefix;

my $q = "/usr/local/sbin/nwstat.pl $host V".$ppp."U$vname V".$ppp."S$vname";
#print "$host, $vname, $critical, $warning ($ppp = $opt_prefix) \n";
#print "$q \n";
my $res = `$q`;
my @aar=split(/\n/, $res);

my $size = $aar[1];
my $used = $aar[0];

if (($size < 1) || ($used < 0)) { exit $ERRORS{'ERROR'}; }
#print "Size: $size, used: $used\n";

my $percent = ($used/$size)*100;
if ($percent > 100) { exit $ERRORS{'ERROR'}; }
printf "Used: %.2f\%\n", $percent;

if ($percent > $critical) { exit $ERRORS{'CRITICAL'}; } # Critical!
if ($percent > $warning) { exit $ERRORS{'WARNING'}; } # Warning!
exit $ERRORS{'OK'}; # Okay


sub print_usage () {
print "Usage: $PROGNAME -H <host> [-v <volumename>] [-w <warn>] [-c <crit>] [-p <prefix>]\n";
}

sub print_help () {
print_revision($PROGNAME,");
print "Copyright © Smithson Inc, 2011\n";
print "\n";
print_usage();
print "\n";
print "<warn> = Signal strength at which a warning message will be generated.\n";
print "<crit> = Signal strength at which a critical message will be generated.\n";
print "<prefix> = Special for signal nwstat, calculated size, free and used as KBytes (value K) or Bytes (value nothing).\n\n";
support();
}


Він, у свою чергу, використовує скрипт nwstat.pl коли-то шедщий в комплекті mrtgext. Йде він зараз — не знаю, тому викладу його сюди.

nwstat.pl
#!/usr/local/bin/perl

#########################################################
# Netware Server Stat Extension to MRTG #
# Client Access #
# #
# This is the "client" portion of the Netware Server #
# stats extension for MRTG. This will open up a #
# connection to the specified server and get the #
# information that you specify. #
# #
#########################################################
# Written by James Drews (drews@engr.wisc.edu) on #
# Version 1.46 #
# URL: #
#http://forge.novell.com/modules/xfmod/project/?mrtgext #
#########################################################
# #
# Feel free to contact me with any questions/comments/ #
# and such. #
# #
#########################################################
# This program is безкоштовний. *NO* warranty is expressed,#
# implied, nor granted to you in any way. Use of this #
# program is at your own risk. Your mileage may vary. #
# This program was packed by weight, not by volume. #
# Some settling may have occurred during shipment. #
#########################################################

#########################################################
# Command Line Usage #
# nwstat.pl host option1 option2 #
# host is where the DNS name of the server to query #
# and option1 and option2 are any combination of the #
# following (case is not important): #
# UTIL1 : 1 minute average CPU utilization #
# UTIL5 : 5 minute average CPU utilization #
# UTIL15 : 15 minute average CPU Utilization #
# LICENSE : Connection License Count #
# CONNECT : number currently licensed connections #
# CONNMAX : Max number licensed connections used #
# CONNPEAK : Peak Connections #
# : (netware 3 = error (-1) ) #
# : (netware 4 = number connections #
# : allocated) #
# NAME : server's name #
# UPTIME : Time that the server is operational #
# VS<vol> : size of the volume <vol> in bytes #
# VF<vol> : bytes free on <vol> #
# VU<vol> : bytes used on <vol> #
# VKS<vol> : size of the volume <vol> in kbytes #
# VKF<vol> : kbytes free on <vol> #
# VKU<vol> : kbytes used on <vol> #
# VP<vol> : bytes of purgable files on <vol> #
# VKP<vol> : kbytes of purgable files on <vol> #
# VNP<vol> : bytes of not-yet-purgable files #
# VKNP<vol> : kbytes of not-yet-purgable files #
# ZERO : Returns the value 0 #
# VOLUMES : Returns the list of mounted volumes #
# : each volume name is on a окремі #
# : line. Used by the nlmcfg.pl script #
# S1 : Long Term Cache Hit Percentage #
# S2 : Current number cache buffers #
# S3 : Number of dirty cache buffers #
# S4 : Cache LRU in seconds #
# S5 : Cache LRU in minutes #
# S6 : Dirty cache buffers as percent of tot #
# S7 : Total cache buffers as percent of #
# original #
# S8 : Original number of cache buffers #
# S9 : SAP object Count #
# S9.x : SAP Object count for service x #
# S10 : CPU Count #
# S11 : IS DS Open Database? 1=yes 0=no #
# S12 : Logins enabled? 1=yes 0=no #
# S13 : DS.NLM Version string #
# S14 : MRTGEXT.NLM Version string #
# S15 : Packet receive buffer count #
# S16 : Get Maximum packet receive buffer cnt #
# S17 : Abended thread count (5.x only) #
S18 : Open file count #
# S19 : OS Version String #
# S20 : Max service processes #
# S21 : Current service processes (5.x only) #
# S22 : Time In Sync To the Network (0=No #
# 1 = yes) #
# S23:<nlm> : Is <nlm> loaded? (0=no,1=yes) #
# S24:<nlm> : Get <nlm>'s version #
# S25 : Minimum Cache Directory Buffers #
# S26 : Maximum Cache Directory Buffers #
# S27 : Current Directory Cache Buffers #
# #
# Example: To get the server utilization for 5 і 15 #
# minutes on the myserv.mydomain.com. #
# #
# nwstat.pl myserv.mydomain.com UTIL5 UTIL15 #
# #
# Example: To graph the disk space on the usage SYS #
# volume on myserv.mydomain.com. #
# #
# nwstat.pl myserv.mydomain.com VFsys VUsys #
#########################################################
# #
# Other notes: #
# The server side NLM can take ALL the options on the #
# command line at once. However, MRTG is written to #
# only graph two variables at a time. Should some #
# ambitious person modify the program to graph more #
# than two items at once, this program can easily be #
# expanded to output more items. #
# #
# The server will stop accepting input at 1023 chars #
# or when it gets the first \n character #
# #
# Thanks to Kevin Keyser <kevin-keyser@uiowa.edu> #
# for fixing the problem of loosing the 'W' char from #
# the server name #
#########################################################

# Required for perl5.
use Socket;
($_, $opt1, $opt2) = @ARGV;

if (!$_) {
print "Usage: $0 HOST OPTION1 OPTION2 \n";
print " where host is the DNS name of the server to query\n";
print " and option1 and option2 are any combination of the\n";
print " following (case is not important):\n";
print " UTIL1 : 1 minute average CPU utilization\n";
print " UTIL5 : 5 minute average CPU utilization\n";
print " UTIL15 : 15 minute average CPU Utilization\n";
print " LICENSE : Connection License count\n";
print " CONNECT : number currently licensed connections\n";
print " CONNMAX : max licensed connections used\n";
print " CONNPEAK : Peak Connections\n";
print " : (netware 3 = error (-1) )\n";
print " : (netware 4 = number connections\n";
print " : allocated\n"; 
print " VF<vol> : bytes free on <vol>\n";
print " VS<vol> : size in bytes of <vol>\n";
print " VU<vol> : bytes used on <vol>\n";
print " VKF<vol> : kbytes free on <vol>\n";
print " VKS<vol> : size in kbytes of <vol>\n";
print " VKU<vol> : kbytes used on <vol>\n";
print " ZERO : returns a zero (0)\n";
print " S1 : Long Term Cache Hit Percentage\n";
print " S2 : Number of Cache Buffers\n";
print " S3 : Number of Dirty Cache Buffers\n";
print " S4 : Cache LRU in seconds\n";
print " S5 : Cahce LRU in minutes\n";
print "\n Example: To graph the disk space on the usage SYS\n";
print " volume on myserv.mydomain.com.\n\n";
die " $0 myserv.mydomain.com VFsys VUsys\n";
}

if (!$opt2) {
printf "No second option specified. MRTG expects two values\n";
die "Use \"ZERO\" for the second option if you only wnat one value.\n";
}

$hostname = $_;

# if you load the NLM with a different port
# from the default, here is where you change it
$port = 9999;

# Open a socket and get the data
($sockaddr,$there,$response,$tries) = ("Snc4x8");
# On Win95, passing a numeric IP address to inet_aton() is slow, so
# detect this case and use a simple conversion. 
chomp ($hostname);
if ($hostname =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)(.*)/ )
{
# $remote_addr = pack('4',"$1.$2.$3.$4");
$remote_addr = "$1.$2.$3.$4";
} else {
$remote_addr = (gethostbyname($hostname))[4]
|| die (host_not_found_error ($hostname, $?));
}

# my $addr_in = 'S n a4 x8';
# $there = pack($addr_in, AF_INET, $port, $remote_addr);
# Конвертує ім'я сервера в бінарну послідовність.
my $iaddr = inet_aton($remote_addr);
# Упаковує все зрозумілу функції connect послідовність.
$there = sockaddr_in($port, $iaddr);
$proto = (getprotobyname ('tcp'))[2];

if (!socket(S,AF_INET,SOCK_STREAM,$proto)) { printf "-1\n-1\n\n\n"; die "$0: Fatal Error. $!\n"; }
if (!connect(S,$there)) { printf "-2\n-2\n\n\n"; die "$0: Fatal Error. $!\n"; }
select(S);$|=1;
select(STDOUT);
print S "$opt1 $opt2 uptime name\r\n";
$in = int(<S>);
print "$in\n";
while($line = <S>) {
print "$line";
}
close(S);


Використовувати його легко і просто:

define command{
command_name check_nwvolsize
command_line $USER1$/check_nwvolsize -H $HOSTADDRESS$ -w $ARG2$ c $ARG3$ -v $ARG1$ -p K
}

Для малювання статистики:

Netware через mrtg даю шаблон

HtmlDir: /data/www/admin/mrtg
ImageDir: /data/www/admin/mrtg/images
Реєстрації: /data/www/admin/mrtg/logs
IconDir: /mrtg/icons
Language: Ukrainian
Options[_]: gauge, noarrow, nopercent, unknaszero
kilo[_]: 1000


PageTop[^]: <b><<<<a href=index_nw6.html>To Index Page</b></a><br><br>
<table width=100% cellspacing=0 cellpadding=5 border=1 bgcolor=#dedede align=center>
<tr><td><center><H4>
PageTop[$]: </td></tr></table>
# ------------------- Common Parameters ------------------

Target[nw6_cpu]: `/usr/local/sbin/nwstat.pl 192.168.2.4 util5 util15`
ShortLegend[nw6_cpu]: %
YLegend[nw6_cpu]: CPU Util (%)
LegendI[nw6_cpu]: 5 minute average CPU utilization
LegendO[nw6_cpu]: 15 minute average CPU utilization
MaxBytes[nw6_cpu]: 100
Title[nw6_cpu]: CPU Utilization Analysis for Server NW6
PageTop[nw6_cpu]: CPU Utilization Analysis for Server NW6 </H4></center>

Target[nw6_conn]: `/usr/local/sbin/nwstat.pl 192.168.2.4 connect s18`
MaxBytes[nw6_conn]: 140000
ShortLegend[nw6_conn]: 
YLegend[nw6_conn]: Connections & Open files
LegendI[nw6_conn]: Number currently licenzed connections
LegendO[nw6_conn]: Open files
Title[nw6_conn]: Connection & Open Files for Server NW6
PageTop[nw6_conn]: Connection & Open Files for Server NW6 </H4></center>

# s8 = Original number of cache buffers
# s2 = Current number cache buffers
Target[nw6_s2]: `/usr/local/sbin/nwstat.pl 192.168.2.4 s2 s8`
MaxBytes[nw6_s2]: 2000000000
ShortLegend[nw6_s2]: 
YLegend[nw6_s2]: Cache Buffers
LegendI[nw6_s2]: Number of Free Cache Buffers
LegendO[nw6_s2]: Number of Total Cache Buffers
Title[nw6_s2]: Number of Cache Buffers for Server NW6
PageTop[nw6_s2]: Number of Cache Buffers for Server NW6 </H4></center>

# s20 = Max service processes
# s21 = Current service processes
Target[nw6_proc]: `/usr/local/sbin/nwstat.pl 192.168.2.4 s21 s20`
MaxBytes[nw6_proc]: 2000000
ShortLegend[nw6_proc]: 
YLegend[nw6_proc]: Processes
LegendI[nw6_proc]: Current service processes
LegendO[nw6_proc]: Max service processes
Title[nw6_proc]: Service processes analysis for Server NW6
PageTop[nw6_proc]: Service processes analysis for Server NW6 </H4></center>

# s15 = Packet receive buffer count
# s16 = Maximum packet receive buffer count
Target[nw6_packet]: `/usr/local/sbin/nwstat.pl 192.168.2.4 s15 s16`
MaxBytes[nw6_packet]: 2000000
ShortLegend[nw6_packet]: 
YLegend[nw6_packet]: Buffers
LegendI[nw6_packet]: Current packet buffers
LegendO[nw6_packet]: Max packet buffers
Title[nw6_packet]: Packet receive buffers count for Server NW6
PageTop[nw6_packet]: Packet receive buffers count for Server NW6 </H4></center>


#---------------------------------------------------------------------------------
# DISKS
#---------------------------------------------------------------------------------
Target[nw6_vol-data]: `/usr/local/sbin/nwstat.pl 192.168.2.4 VKUDATA VKSDATA`
MaxBytes[nw6_vol-data]: 500000000000
kilo[nw6_vol-data]: 1024
kMG[nw6_vol-data]: k,M,G,T,P
ShortLegend[nw6_vol-data]: b
YLegend[nw6_vol-data]: Disk space
LegendI[nw6_vol-data]: Kbytes used on volume DATA
LegendO[nw6_vol-data]: Size of volume DATA in Kbytes
Title[nw6_vol-data]: Volume DATA statistics for server NW6
PageTop[nw6_vol-data]: Volume DATA statistics for Server NW6 </H4></center>

Target[nw6_pur_vol-data]: `/usr/local/sbin/nwstat.pl 192.168.2.4 VKPDATA VKNPDATA`
MaxBytes[nw6_pur_vol-data]: 1000000000000
kilo[nw6_pur_vol-data]: 1024
kMG[nw6_pur_vol-data]: k,M,G,T,P
ShortLegend[nw6_pur_vol-data]: b
YLegend[nw6_pur_vol-data]: Purgable files
LegendI[nw6_pur_vol-data]: Kbytes of purgable files on volume DATA
LegendO[nw6_pur_vol-data]: Kbytes of not-yet-purgable files on volume DATA
Title[nw6_pur_vol-data]: Volume DATA purgable files statistics for server NW6
PageTop[nw6_pur_vol-data]: Volume DATA purgable files statistics for Server NW6 </H4></center>

Target[nw6_vol-sys]: `/usr/local/sbin/nwstat.pl 192.168.2.4 VKUSYS VKSSYS`
MaxBytes[nw6_vol-sys]: 500000000000
kilo[nw6_vol-sys]: 1024
kMG[nw6_vol-sys]: k,M,G,T,P
ShortLegend[nw6_vol-sys]: b
YLegend[nw6_vol-sys]: Disk space
LegendI[nw6_vol-sys]: Kbytes used on volume SYS
LegendO[nw6_vol-sys]: Size of volume SYS in Kbytes
Title[nw6_vol-sys]: Volume SYS statistics for server NW6
PageTop[nw6_vol-sys]: Volume SYS statistics for Server NW6 </H4></center>


З нього зрозуміло, як можна моніторити процесор, ОЗП, буфера на Netware-сервері через mrtgext, якщо це комусь ще треба.

Моніторинг Novell (вже не, але не суть) OES.
OES — це Open Enterprise Server. В основі OES лежить SUSE Linux, тому базовий моніторинг тут ті ж, що і для linux, а ось як моніторити додаткові сервіси зараз опишу.

Знову ж на першому місці буде моніторинг томів:

get-voldata.pl
#!/usr/local/bin/perl
#
# © Smithson Inc
#
#

#use strict;
use lib "/usr/local/libexec/nagios";
use utils qw($TIMEOUT %ERRORS &print_revision &support);
use vars qw($PROGNAME);
use Getopt::Long;
use Time::gmtime;
use vars qw($opt_V $opt_h $verbose $opt_w $opt_c $opt_H $volname $opt_mode $mode);

$PROGNAME = `basename $0`;

Getopt::Long::Configure('bundling');
GetOptions
("V" => \$opt_V, "version" => \$opt_V,
"h" => \$opt_h, "help" => \$opt_h,
"v=s" => \$volname, "volname" => \$volname,
"w=s" => \$opt_w, "warning=s" => \$opt_w,
"c=s" => \$opt_c, "critical=s" => \$opt_c,
"m=s" => \$opt_mode, "mode=s" => \$opt_mode,
"H=s" => \$opt_H, "hostname=s" => \$opt_H);


if ($opt_V) {
print_revision($PROGNAME,"); #'
exit $ERRORS{'OK'};
}

if ($opt_h) {
print_help();
exit $ERRORS{'OK'};
}

$opt_H = shift unless ($opt_H);
my $host = $1 if ($opt_H =~ m/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+|[a-zA-Z] [a-zA-Z0]+(\.[a-zA-Z] [a-zA-Z0]+)*)$/);
if (!(defined($host))) { print_usage(); exit $ERRORS{'ERROR'}; };

($opt_c) || ($opt_c = shift) || ($opt_c = 95);
my $critical = $1 if ($opt_c =~ /([0-9]+)/);

($opt_w) || ($opt_w = shift) || ($opt_w = 90);
my $warning = $1 if ($opt_w =~ /([0-9]+)/);

($volname) || ($volname = shift) || ($volname = 'SYS');
my $vname = $volname;

my $mode = 0;

($opt_mode) || ($opt_mode = shift) || ($opt_mode = 'nagios');
if ($opt_mode =~ /mrtg/i) { $mode = 1; }

my $servname = $host;
my $uptime = ";

my $community = 'ISOlanf';
my $SNMP = "/usr/local/bin/snmpget -2c v -c $community";
my $snmpwalk = "/usr/local/bin/snmpwalk -2c v -c $community";

my $OID_NAME = 'SNMPv2-MIB::sysName.0';
my $OID_UPTIME = '.1.3.6.1.2.1.1.3.0';
my $OID_SIZE = 'HOST-RESOURCES-MIB::hrStorageSize';
my $OID_USED = 'HOST-RESOURCES-MIB::hrStorageUsed';
my $OID_DESC = 'HOST-RESOURCES-MIB::hrStorageDescr';

my $pool = '.pools/';

my $n=getvol($host, $vname);
if ($n == 0) { exit $ERRORS{'UNKNOWN'}; }
my $percent = getInfo($host, $n);

if ($mode == 0) { #nagios
if ($percent > 100) { exit $ERRORS{'ERROR'}; }
printf "Used: %.2f\%\n", $percent;

if (($percent > $critical) || ($percent == 0)) { exit $ERRORS{'CRITICAL'}; } # Critical!
if ($percent > $warning) { exit $ERRORS{'WARNING'}; } # Warning!
exit $ERRORS{'OK'}; # Okay
};
if ($mode == 1) { # mrtg 
print $percent;
exit (0);
}
# ================================================================
sub getvol {
my $ip = shift;
my $v = shift;

my $ret = 0; 

my $seek = $pool.$v;
my @n = getDesc($ip);

foreach $l (@n) {
if ($l =~ /$OID_DESC\.(\d+).+$seek/i) {
return $1;
}
};

return $ret;
}
# ================================================================
sub getInfo {
my $ip = shift;
my $n = shift;
my $ret = ";

$servname = getSNMPdata($ip, $OID_NAME);
my $size = getSNMPdata($ip, $OID_SIZE.'.'.$n); 
my $used = getSNMPdata($ip, $OID_USED.'.'.$n); 
if ($size < 1) { return; }
$ret = ($used/$size)*100;
if ($mode == 1) { 
$used = $used*4;
$size = $size*4; 
$ret = "$used\n$size\n$uptime\n$servname\n";
}
return $ret;
}

# ================================================================
sub getSNMPdata {
my $ip = shift;
my $snmpquery = shift;
my $q, $dat;

$q = "$SNMP $ip $snmpquery | awk '{print \$4}'";
$dat = `$q`;
chomp $dat;
if (length($dat) < 1) {
return 'U';
}
return $dat;
}
# ================================================================
sub getSNMPstring {
my $ip = shift;
my $snmpquery = shift;
my $q, $dat;

$q = "$SNMP $ip $snmpquery";
$dat = `$q`;
chomp $dat;
if (length($dat) < 1) {
return ";
}
if ($dat =~ /= STRING:\ (.+)/) { $dat = $1 };
return $dat;
}
# ================================================================
sub getDesc {
my $ip = shift;
my @ret = "; 
my $q = "$snmpwalk $ip $OID_DESC";

@ret = `$q`;
return @ret;
};
# ================================================================
sub print_usage () {
print "Usage: $PROGNAME -H <host> [-v <volumename>] [-w <warn>] [-c <crit>] [-m <mode>]\n";
}
# ================================================================
sub print_help () {
print_revision($PROGNAME,");
print "Copyright © Smithson Inc, 2013 \n";
print "\n";
print_usage();
print "\n";
print "<warn> = Signal strength at which a warning message will be generated.\n";
print "<crit> = Signal strength at which a critical message will be generated.\n";
print "<mode> = Used mode - nagios -> return percents of volume used, mrtg -> return used and max size of volume for mrtg\nBy use default 'nagios'\n\n";
support();
};
# ================================================================


Цей Скрипт в мене універсальний для nagios і для mrtg, тому з параметром m mrtg він видає циферки розміру (зайнято всього) тома, як їх чекає mrtg, а без нього або з параметром m nagios видає відповідь, типовий для плагіна nagios.

В якості параметрів він приймає ім'я або ip сервера та ім'я тома. Тому шукаються в списку змонтованих, точки монтування .pools/ИМЯТОМА (технічні для OES) ігноруються. Якщо тому не знайдено, повертається розмір 0 і ситуація CRITICAL (у нас багато «зовнішніх» — fc або iscsi — томів і треба ловити випадки їх відпадання).

За замовчуванням аналізується те SYS (тяжку спадщину Netware, є у кожного OES-сервера, але абсолютно не потрібний і не цікавий).

Використовується в nagios звичайним чином

define command{
command_name check_oesvolsize
command_line $USER1$/get-voldata.pl -H $HOSTADDRESS$ -v $ARG1$ -w $ARG2$ c $ARG3$
}

у mrtg так:

`/data/rrdtool/oes/get-voldata.pl -H ip-сервера -v ИМЯТОМА -m mrtg`


Тепер про сервіс друку. Принтери можна моніторити самостійно, але якщо у вас iPrint, то цікаво моніторити принтери «з точки зору сервера». І для цього є скриптик:

check_iprinters.pl
#!/usr/bin/perl -w
#
# @File check_iprinters.pl
# @Author dbenjamin
# @Created Aug 4, 2015 2:59:02 PM
# Licence : GPL - http://www.gnu.org/licenses/lgpl-3.0.html
#

use strict;
use LWP::Simple;
use HTML::TreeBuilder;
use Getopt::Long;
my $nagios_plugins_utils =
# "/usr/lib/nagios/plugins/utils.pm"; #used to test for the library
"/usr/local/libexec/nagios/utils.pm"; #used to test for the library
die "\nLooking for nagios utils.pm at $nagios_plugins_utils"
unless ( -e $nagios_plugins_utils );
use lib "/usr/local/libexec/nagios"; #just use the path here
use utils qw(%ERRORS $TIMEOUT);

my ( $opt_h, $opt_I, $opt_Q, $opt_v, $opt_P, $opt_V );
my ( $printer_state, $accepting_jobs, $jobs_scheduled );
my $i = 0; #iteration holder
$opt_P = '631';

alarm($TIMEOUT);

sub print_version {
print "File: check_iprinters.pl\n";
print "Author: dbenjamin\n";
print "Created: Aug 4, 2015\n";
print "Release: 0.0.1\n";
print "Tested against Novell iPrint Server 6.7.0.20150629-0.6.6, ";
print "running on SLES 11, SP3 with OES 11, SP2.\n";
exit $ERRORS{'UNKNOWN'};
}

sub print_exit {
print
"Usage: $0 -I <host address> -Q <queue name> [-P <port> default=631] [-v enable verbose] [--version]\n\n";
exit $ERRORS{'UNKNOWN'};
}

sub print_verbose {
print "Printer State: $printer_state\n";
print "Printer is Accepting Jobs: $accepting_jobs\n";
print "Jobs Scheduled: $jobs_scheduled\n";
}

GetOptions(
"version" => \$opt_V,
"h" => \$opt_h,
"help" => \$opt_h,
"I=s" => \$opt_I,
"Q=s" => \$opt_Q,
"P:s" => \$opt_P,
"v" => \$opt_v,
) or print_exit;

if ($opt_V) {
print_version;
}

if ($opt_h) {
print_exit;
}

if ( !$opt_I ) {
print "No Host address specified\n";
print_exit;
}
if ( !$opt_Q ) {
print "No Queue name specified\n";
print_exit;
}

if ( ( $opt_I eq ") or ( $opt_Q eq " ) ) { print_exit; }
my $tree = new HTML::TreeBuilder->new;
my $url = "http://$opt_I:$opt_P/ipp/$opt_Q";
my $result = get($url);
die "\nCouldn't get $url" unless defined $result;
$tree->parse($result);
my @tbrows = $tree->look_down( '_tag', 'TR' );
die "No response, check the URL for errors: $url\n\n" unless @tbrows;
foreach $i ( 2 .. 4 ) {
my @td = $tbrows[$i]->look_down( '_tag', 'TD' );
if ( $i == 2 ) { $printer_state = $td[1]->as_text; }
if ( $i == 3 ) { $accepting_jobs = $td[1]->as_text; }
if ( $i == 4 ) { $jobs_scheduled = $td[1]->as_text; }
}
if ( ( $printer_state =~ /error/i ) & ( $printer_state =~ /empty/i ) ) {
if ($opt_v) { print_verbose }
else { print "$printer_state\n\n"; }
exit $ERRORS{'WARNING'};
}
else {
if ( $printer_state =~ /error/i ) {
if ($opt_v) { print_verbose }
else { print "$printer_state\n\n"; }
exit $ERRORS{'CRITICAL'};
}
}
if ( $opt_v ) { print "jobs=$jobs_scheduled\n"; }
exit $ERRORS{'OK'};

Скрипт не мій, але дуже корисний. У нагиос його можна використовувати так:

define command{
command_name check_iprinter_q
command_line $USER1$/check_iprinters.pl -I $HOSTADDRESS$ Q $ARG1$ $ARG2$
}

define service{
use generic-service
name iprint_q
host_name iprint
contacts printer-admins
check_period 24x7 
max_check_attempts 3
normal_check_interval 10 
retry_check_interval 5 
notifications_enabled 0
notification_options c,r
notification_interval 60 
notification_period workhours
icon_image printer.gif
flap_detection_enabled 0
register 0
}

define service{
use iprint_q
service_description AHO-2430
check_command check_iprinter_q!AHO-2430!-v
}

Коли принтерів у вас кілька десятків (у мене їх ближче до сотні), вести такий список непросто, але зате ви відразу бачите, де скінчилася папір або картридж, який принтер вже 40+ днів відключений (у нас 40 днів відключення — поріг на зняття принтера) або стоїть багато днів без паперу або картриджа. Користь є.

Фух, багато вийшло. Поки зупинюся. Якщо стаття сподобається, буде друга частина — про моніторинг ДБЖ, Synology, vmware і принтерів, але вже як принтерів, а не як об'єктів iPrint.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.