• Publicidad

return error en script

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

return error en script

Notapor natxo » 2009-04-29 09:40 @444

Hola.

Tengo que controlar el estado de los discos de unos servidores Fujitsu Primergy y lo puedo hacer con SNMP (con snmpwalk). He hecho un programilla que en sí funciona pero me falta la guinda :-)

Aquí está el código:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
#===============================================================================
#
#         FILE:  check-fs-array.pl
#
#        USAGE:  ./check-fs-array.pl  
#
#  DESCRIPTION:  check disk array controller health through SNMP
#
#      OPTIONS:  ---
# REQUIREMENTS:  snmputils (snmpwalk, in particular)
#         BUGS:  probably a lot <img src="http://perlenespanol.com/foro/images/smilies/icon_smile.gif" alt=":)" title="Smile" />
#        NOTES:  ---
#       AUTHOR:  José Asenjo (JA)
#      COMPANY:  
#      VERSION:  1.0
#      CREATED:  04/20/2009 02:45:14 PM
#     REVISION:  ---
#===============================================================================

use strict;
use warnings;
use Getopt::Long;

# some variables

my $host;

Getopt::Long::Configure("bundling");
GetOptions(
    'H|host=s'      =>   \$host,
    'u|?|usage'     =>  sub { usage(); },
    'h|help'        =>  sub { help(); },
    ) or help();

# oid is here nummeric form of
# .iso.org.dod.internet.private.enterprises.sni.sniProductMibs.fscRAIDMIB.svrObjects.svrStatus.
my $oid_srvStatus = ".1.3.6.1.4.1.231.2.49.1.3";
my $number_of_lines = 0;
my $ok_result = 0 ;
my $failure_result = 0 ;

if ( !defined $host ) {
    die "I need a hostname. See $0 --help for details\n";
}

check_srvStatus();

   
sub check_srvStatus {
    open (PIPE, "snmpwalk $host -c public -v 1 -m FSC-RAID-MIB $oid_srvStatus |")
    or die "cannot snmpwalk to $host: $!\n";
       
    while ( my $result =  (<PIPE>) ) {
        # count number of lines in result of query
        $number_of_lines++ ;
        chomp $result ;
        if ( $result =~ m/.*INTEGER: ok.*$/ ) {
            $ok_result++;
        }
        if ( $result =~ m/.*INTEGER: .*failure.*$/ ) {
            $failure_result++ ;
        }
    }      
       
    if ( $failure_result > 0 ) {
        print "WARNING: there is a problem with the logical or the physical
        volume of the disk array. Check https://$host:3263 for details\n"
;
        exit 1;
    }
       
    if ($number_of_lines == $ok_result ) {
        print "OK: All logical and physical devices in array are working fine\n";
        exit 0;
    }  
    #my ( $par1 )   = @_;
    #return ;
}   # ----------  end of subroutine check_srvStatus  ----------
   

sub usage {
    print "Usage: $0 --host [enter]\n";
    print "See $0 --help for details\n";
    return;
}   # ----------  end of subroutine usage  ----------
   

sub help {
    usage();
my $heredoc = <<EOF;
        -H, --host
        -u, --usage
        -h, --help
EOF

    print $heredoc;
    exit 0;
}   # ----------  end of subroutine help  ----------
Coloreado en 0.005 segundos, usando GeSHi 1.0.8.4



Si ejecuto el programa con una máquina existente y accesible funciona bien:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
$ ./check-fs-array -H izvm05
OK: All logical and physical devices in array are working fine
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


Pero si la ejecuto para un servidor que no existe o no está disponible también me da resultado Ok aunque sea erróneo:

Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
./check-fs-array -H izvm06
getaddrinfo: izvm06 Name or service not known
snmpwalk: Unknown host (izvm06)
OK: All logical and physical devices in array are working fine
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


El error está claro, no puede resolver el nombre de la máquina, snmpwalk no encuentra la máquina por consiguiente, pero sin embargo me devuelve el resultado equivocado OK.

¿Cómo puedo terminar el script si la llamada a snmpwalk no termina en éxito? Es el problema de mezclar Perl con comandos de la shell.
saludos,
Natxo Asenjo
natxo
Perlero nuevo
Perlero nuevo
 
Mensajes: 76
Registrado: 2007-08-09 16:22 @723
Ubicación: Países Bajos

Publicidad

Notapor explorer » 2009-04-29 10:09 @464

Quizás porque $number_of_lines y $ok_result tienen el mismo número de líneas: 0.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor natxo » 2009-04-29 13:47 @616

Tienes razón en que ambas variables tienen el mismo resultado.

Ahora bien, ¿cómo puedo verificar el resultado de la llamada a snmpwalk? Porque aquí está el problema, creo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
open (PIPE, "snmpwalk $host -c public -v 1 -m FSC-RAID-MIB $oid_srvStatus |")
    or die "cannot snmpwalk to $host: $!\n";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Lo que voy a probar la semana que viene (lo siento por los que tengan que currar, aquí en NL tenemos puente por el cumpleaños de la reina) es a meter un control de DNS. Si el servidor no tiene un record A entonces corto el programa con un error 1 para que nagios me avise de que hay algo que no va bien. He probado esto y me funciona:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use strict;
use warnings;

use Net::DNS;

my $host =shift;

print $host, "\n";

my $resolver = Net::DNS::Resolver->new;
my $dnsquery = $resolver->search($host);

if ($dnsquery) {
    for my $dnsanswer ($dnsquery->answer)   {
        next unless $dnsanswer->type eq "A";
        print $dnsanswer->address, "\n";
    }
}
else {  
        warn "WARNING: Host does not exist in dns", $resolver->errorstring, "\n";
        exit 1
}
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


así que si mis compañeros modifican los controles de nagios y el nuevo control no está en DNS, falle.

Creo que esto será suficiente.
saludos,
Natxo Asenjo
natxo
Perlero nuevo
Perlero nuevo
 
Mensajes: 76
Registrado: 2007-08-09 16:22 @723
Ubicación: Países Bajos

Notapor explorer » 2009-04-29 14:17 @637

He consultado las páginas de manual de snmpwalk y snmpcmd para ver si devuelven algún valor de estado, pero no hay nada de eso o no lo he encontrado.

Tu ejecutas el comando con una tubería, porque quieres recoger su salida, pero el caso es que obtendrías el mismo resultado si lo ejecutaras con
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my @resultado = qx(...);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
y luego ejecutaras un bucle por cada elemento de @resultado.

Y si snmpwalk no devuelve valores de estado -como los que obtenemos con la función system()-, entonces solo queda analizar lo que el comando nos devuelve.

Por ejemplo, si después del bucle la variable $ok_result es 0, pues entonces es quizás que exista un error.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor natxo » 2009-04-29 15:10 @673

Lo mejor será que explique la situación concreta. Los servidores tienen una tarjeta de control para los discos (disk array controller) y mediante SNMP se puede leer el estado de los discos con un comando como éste:

Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
$ snmpwalk server -c public -v 1 -m FSC-RAID-MIB .1.3.6.1.4.1.231.2.49.1.3

FSC-RAID-MIB::svrStatusLogicalDrives.0 = INTEGER: ok(1)
FSC-RAID-MIB::svrStatusPhysicalDevices.0 = INTEGER: ok(1)
FSC-RAID-MIB::svrStatusControllers.0 = INTEGER: ok(1)
FSC-RAID-MIB::svrStatusOverall.0 = INTEGER: ok(1)
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

(no voy a explicar aquí cómo funciona SNMP porque no viene al caso).

El tema es que este resultado es el bueno. Tanto el volumen lógico de los discos como los discos en sí, como la controladora/tarjeta están bien y nos informan que su estado es ok(1);

si saco un disco (en los servidores se pueden sacar los discos en directo, en este caso si fuerzo una avería del disco sacándolo de la bahía de discos):
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
$ snmpwalk server -c public -v 1 -m FSC-RAID-MIB .1.3.6.1.4.1.231.2.49.1.3
FSC-RAID-MIB::svrStatusLogicalDrives.0 = INTEGER: prefailure(2)
FSC-RAID-MIB::svrStatusPhysicalDevices.0 = INTEGER: failure(3)
FSC-RAID-MIB::svrStatusControllers.0 = INTEGER: prefailure(2)
FSC-RAID-MIB::svrStatusOverall.0 = INTEGER: prefailure(2)
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


vemos que el volumen lógico de disco (son dos, uno está fuera y el servidor sigue funcionando en el disco restante) ha cambiado de estado de ok(1) a prefailure(2); uno de los discos físicos ha fallado (efectivamente, lo hemos sacado) y su estado es failure(3). Por esto busco la cadena "ok" y ".*failure" (incluye prefailure, pues) para ver si han fallado los discos o no.

Los valores $number_of_lines y $ok_result los he predefinido al principio (0), así que si no se ejecuta el comando snmpwalk porque el argumento $host o bien no existe o bien no se resuelve mediante DNS, el resultado es que son iguales, ambos son 0 y por tanto se cumple el control
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
if ($number_of_lines == $ok_result ) {
        print "OK: All logical and physical devices in array are working fine\n";
        exit 0;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


He visto que hay un módulo Net::SNMP, tengo que mirarlo con más detenimiento. Supongo que dicho módulo tiene incluidos controles en cuanto al éxito/fracaso de los métodos implementados.
saludos,
Natxo Asenjo
natxo
Perlero nuevo
Perlero nuevo
 
Mensajes: 76
Registrado: 2007-08-09 16:22 @723
Ubicación: Países Bajos

Notapor explorer » 2009-04-29 15:51 @702

Pues... entonces te valdría con poner un if() dentro del que muestras ahí:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
if ($number_of_lines == $ok_result ) {
    if ($ok_result == 0) {
        print "ERROR: No hubo respuesta\n";
        exit 1;
    }
    else {
        print "OK: All logical and physical devices in array are working fine\n";
        exit 0;
    }
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor natxo » 2009-04-29 16:34 @732

¡Jo!, pues tienes toda la razón. Es la solución más obvia. Gracias :)
saludos,
Natxo Asenjo
natxo
Perlero nuevo
Perlero nuevo
 
Mensajes: 76
Registrado: 2007-08-09 16:22 @723
Ubicación: Países Bajos


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: Google [Bot] y 1 invitado

cron