Trucos Unix: ¿Como saber si un demonio está arriba o no con SNMP?

Usted tiene el siguiente problema: Tiene un par de demonios que quiere monitorear, pero no puede revizar directamente si están arriba ya que o hablar el protocolo nativo es complicado (por ejemplo para monitorear NTP desde Perl quizas tenga que instalar Net::NTP pero eso le pide Perl 5.8.0 y usted tiene 5.6.1), el demonio no va a hablar directamente con usted (por ejemplo un ACL para evitar que el demonio sea hackeado) o simplemente el demonio no acepta conexiones (por ejemplo un programa en Perl o Java que corre todo el tiempo pero no escucha en ningún puerto).

¿Todo está perdido?. No, si usted tiene la suerte de que puede correr Net-SNMP en la máquina en cuestion, entonces sólo tiene que agregar una línea en la configuración de el agente para ver si el demonio está arriba. Ya antes yo les habia hablado de Net-SNMP por acá y hasta les había dejado un archivo de configuración de referencia.

Una ventaja de monitorear demonios de esta manera es que el protocolo de SNMP está especialmente diseñado para consultar una cantidad larga de dispositivos y valores, por lo que la sobrecarga de datos en la red debería ser menos que preguntar directamente a los servicios nativos; Lo otro es que también usted se ahorra el trabajo de hablar varios protocolos y le deja el trabajo a SNMP de ver si el demonio está arriba (si, ya se, usted siempre puede ver si el puerto está abierto con un simple socket peo esa no es una transacción de verdad, además de que usted tiene que echar el código). En este caso, es una virtud el ser perezoso…

El algoritmo va de la siguiente manera:

  1. Haga una transferencia de la zona de su servidor de DNS (o haga un port scanning de toda la red). En mi opninión es más rápido la transferencia ya que así solamente contactamos a los servidores que realmente están registrados (usted tiene un SA que mantiene al dia el DNS, ¿no es asi?)
  2. Por cada registro tipo A (ignore CNAMES, PTR, MX, etc) haga una consulta de el OID de el servicio a monitorear (especifico de el agente Net-SNMP). La razón es que el indice cambia dependiendo de como nuestro SA haya configurado el archivo ‘snmpd.conf’. Si no tiene indice es que el servicio no está siendo monitoreado por el agente, asi que ignore esta maquina.
  3. Si el indice existe, entonces obtenga la bandera de error. Si es igual a 1, es que el demonio no estaba corriendo, asi que reporte el error.

Hacer este programa me tomó 1 hora, mientras escuchaba Apocalyptica y limpiaba las cagadas, por lo que no es el fin del mundo:

   1:#!/usr/bin/perl
2:
3:use Net::DNS;
4:use Net::SNMP;
5:use strict;
6:
7:use constant PORT =>
8: 161;
9:use constant BASE_OID =>
10: '.1.3.6.1.4.1.2021.2';
11:use constant INDEX_OID =>
12: BASE_OID . '.1.2';
13:use constant STATUS_OID =>
14: BASE_OID . '.1.100';
15:use constant VERSION =>
16: 2;
17:use constant UNKNOWN_INDEX =>
18: -1;
19:
20:use constant ERROR_CODE =>
21: 192;
22:
23:use constant OK_CODE =>
24: 0;
25:
26:if ((scalar(@ARGV)) != 4) {
27: &usage();
28: exit ERROR_CODE;
29:}
30:
31:my $res = Net::DNS::Resolver->new;
32:$res->nameservers($ARGV[0]);
33:# Perform a DNS zone transfer
34:my @zone = $res->axfr($ARGV[1]);
35:foreach my $rr (@zone) {
36: if ($rr->type eq "A") {
37: my $name = $rr->name;
38: printf "%s\n", $name;
39: my ($session, $error) = Net::SNMP->session(
40: -hostname => $name,
41: -community => $ARGV[3],
42: -version => VERSION,
43: -port => PORT
44: );
45: my $result = $session->get_table(
46: -baseoid => INDEX_OID
47: );
48: if (! defined $result) {
49: printf "\t[INFO]: No response from, %s\n", $name;
50: } else {
51: my $index = UNKNOWN_INDEX;
52: foreach my $key (keys %${result}) {
53: # The index position will depend of the order given by the SA,
54: # on the snmpd.conf file, so it is better so look for it!
55: if ($$result{$key} eq "$ARGV[2]") {
56: my @tokens = split('\.', $key);
57: $index = $tokens[scalar(@tokens)-1];
58: }
59: }
60: # It is being monitored?
61: if ($index == UNKNOWN_INDEX) {
62: print "\t[INFO]: Daemon not being monitored!\n";
63: } else {
64: # Now get the status of the daemon
65: my $key = STATUS_OID . "\.$index";
66: my $result2 = $session->get_request(
67: -varbindlist => [$key]
68: );
69: if (! defined $result2) {
70: printf "\t[ERROR]: Unable to poll %s\n", $name;
71: } else {
72: if ($$result2{$key} == 0) {
73: print "\t[INFO]: Service is OK\n";
74: } else {
75: printf "\t[WARNING]: Service is not OK on '%s', status=%s\n", $name, $$result2{$key};
76: }
77: }
78: }
79: }
80: my $error_message = $session->error;
81: if ($error) {
82: printf "\t[ERROR]: %s, %s\n", $name, $error;
83: }
84: if (defined $session) {
85: $session->close;
86: }
87: }
88:}
89:exit OK_CODE;
90:
91:sub usage() {
92:print << "EOF";
93:Usage mode:
94: quick_test.plx nameserver dnsdomain daemonname snmpcommunity
95:
96:Where:
97: nameserver - DNS from where we will pull the DNS zone
98: dnsdomain - Full DNS domain to check
99: daemonname - The process to check for (ntpd, ssh)
100: snmpcommunity - The SNMP community string
101:
102:To read the documentation of the script, do the following:
103:
104:perldoc quick_test.plx
105:
106:EOF
107:}
108:__END__
109:
110:=head1 NAME
111:
112:quick_test.plx - A quick script to check the status of programs running on a Linux server,
113:asuming than the DNS server list is up to date and than the Net-SNMP daemon is running!
114:
115:=head1 DESCRIPTION
116:
117:=head2 DNS SERVER CONFIGURATION
118:
119:Make sure you can do zone transfers from your Perl client; Asuming than '10.1.50.254' is your IP address:
120:
121:allow-transfer { 127.0.0.1; 10.1.50.254; };
122:
123:Our you will get the following error:
124:
125: Mar 1 17:40:18 XXX named[28161]: client 10.1.50.254#59195: zone transfer 'elangelnegro.blogspot.com/IN' denied
126:
127:=head2 SNMP CLIENT CONFIGURATION
128:
129:Make sure than the monitoring of the SNMP daemon is enabled on all the servers (/etc/snmp/snmp.conf):
130:
131:# snmpwalk -v 2c -h localhost public .1.3.6.1.4.1.2021.2
132:proc snmpd 1 1
133:proc sshd
134:proc syslogd 1 1
135:proc ypbind 10 1
136:proc portmap 1 1
137:proc ntpd 1 1
138:proc crond 1 1
139:
140:=head1 AUTHOR
141:
142:Jose V Nunez Zuleta
143:
144:=head1 BLOG
145:
146:El Angel Negro - http://elangelnegro.blogspot.com
147:
148:=head1 LICENSE
149:
150:GPL
151:
152:=cut

La salida de ejemplo:

[root@XXX lucifer]# ./quick_test.plx server dnsdomain ntpd community-string
server1.dnsdomain
[INFO]: Daemon not being monitored!
server2.dnsdomain
[INFO]: No response from, server2.dnsdomain
server2.dnsdomain
[INFO]: No response from, server2.dnsdomain
server3.dnsdomain
[INFO]: No response from, server3.dnsdomain
server4.dnsdomain
[INFO]: No response from, server4.dnsdomain
server5.dnsdomain
[INFO]: Service is OK
server6.dnsdomain
[INFO]: Service is OK
……

¿Como lo puede mejorar?

Puede bajarselo desde acá.

2 thoughts on “Trucos Unix: ¿Como saber si un demonio está arriba o no con SNMP?

  1. Hola!,
    No lo he ejecutado, pero voy a compararlo con el que tenemos para registrar los eventos con el NAGIOS, sin embargo me gustaría hacer la prueba y ver si puedo enviar las salidas a una especie de DB tipo RRDTOOL

    Muy bueno!

  2. Hola Andrés, gracias por visitar mi Blog.

    ¿Ya has probado a OpenNMS? En mi opninión es mucho mejor que Nagios.

    Por cierto, publiqué otro programa similar en el blog, quizas te interese.

    JV.

Comments are closed.