Página 1 de 2

Acceso a routers CISCO

NotaPublicado: 2006-08-11 09:19 @430
por explorer
Yo tuve que hacer eso muchas veces estos años pasados. Lo solución fue ejecutar el comando ping al servidor y ver si ha respondido al paquete. Eso, con los backticks o con qx() puedes ejecutar el comando ping y obtener el resultado. Luego ver si ha respondido o no.

Vamos, básicamente sería algo así:
Código: Seleccionar todo
$ping = system("ping -q -W 4 -c 1 217.127.89.51 > /dev/null");
print $ping;

siendo:
* -W 4 indica que esperamos un máximo de 4 segundos
* -c 1, que enviamos un solo paquete ICMP
* la ip indicada es la de nuestro servidor

El resultado de ejecutar el comando ping será:
* ==0: El servidor ha respondido
* <>0: No ha respondido

En CPAN tienes el módulo Net::Ping, que hace justo eso:
Código: Seleccionar todo
use Net::Ping;
$servidor = "271.127.89.50";
$p = Net::Ping->new();
print "$servidor está vivo.\n" if $p->ping($servidor);
$p->close();

NotaPublicado: 2006-08-12 20:39 @902
por explorer
Acaba de salir un código parecido en perlmonks que hace algo parecido, sólo que es un monitor permanente de la conexión:
Código: Seleccionar todo
#!/usr/bin/perl

use strict;
use POSIX qw(setsid);
use Net::Ping;

{ fork and exit; setsid }

my $router = q{default gw ip};
my $net    = Net::Ping->new;

sleep 5, $net->ping($router, 1) or `inet` while 1


En principio, he entrado aquí:
http://perlmonks.org/?sourceid=Mozilla- ... ton=Search

Hay muchas preguntas e informaciones que te pueden interesar. He visto incluso que hay mucho código.

Pero la solución, como siempre, viene de leer el manual. De Net::Telnet::Cisco, me dice que este módulo está basado en Net::Telnet. Allí veo que hay un párrafo que pone:
Errors such as timing-out are handled according to the error mode action. The default action is to print an error message to standard error and have the program die. See the errmode() method for more information.
que en español quiere decir, más o menos, que
Errores como timeout se manejan de acuerdo a la acción modo error. La acción por defecto es pintar el mensaje de error y que muera el programa. Ver el método errmode() para más información.
Y eso es lo que te pasa: se produce un timeout, sale el mensaje y se muere el programa.

Lo que hay que hacer luego es averiguar cómo funciona la función errmode(), y según el manual, se le puede decir que haga varias cosas:
  • que muera el programa (que es lo que hace por defecto).
  • que haga un simple return (devuelve el mensaje a la función donde ocurrió el error y continúa.
  • Ejecutar tu propio código
He modificado tu código, pero no lo he probado. Ya me dirás...

He hecho tres cambios: ajustar el valor de errmode dos veces, la primera de ellas con una subrutina que pinte el mensaje de error y nada más. Y luego, en el momento del login, le he añadido un modificador next para que, en caso de que falle el login, lo intenté con el siguiente router.

También he cambiado la lógica del programa, pues tenías puesto que se conectara una vez para saber el nombre del router, desconectarte, y volver a conectarte, con la difeerencia de indicar el registro de actividad (log). Ahora sólo se conecta una vez.

Si tienes algún problema con la subrutina del primer errmode, cámbiala a 'return'.

Ya me dirás.

NotaPublicado: 2006-08-22 17:30 @770
por explorer
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
#
# Comprobación de estado de los router CISCO
#
# Joaquín Ferrero. Agosto 2006
#

use DateTime;
use Net::Telnet::Cisco;

use warnings;
use strict;

## Configuración ####################################################
my $username = 'backup';            # Acceso a los router
my $password = 'pepino';

my $lista_router   = 'hosts.cfg';   # Listados
my $lista_comandos = 'comandos.cfg';

use constant DEBUG => 1;            # Informar de lo que va haciendo
## Fin configuración ################################################

## Proceso ##########################################################
#
#:Leeremos la lista de router a comprobar desde un fichero externo
#:Leeremos la lista de comandos a ejecutar en cada router
#:Por cada router
#:  Ejecutaremos en él una lista de comandos
#:
#
# El resultado queda en los registros de actividad,
# que tendrán la forma: nombre_de_router-fecha.log
# siendo fecha de la forma ISO8601: YYYY-MM-DDTHH:MM:SS
# siendo la hora referida a la hora local.
#
#####################################################################

## Leer lista de router
my @routers;
{
    open ROUTERS,"<$lista_router"
        or die "ERROR: No encuentro $lista_router: $!\n";

    chomp ( @routers = <ROUTERS> );

    close ROUTERS;

    if (DEBUG) {
        print "Host $_: $routers[$_]\n" for 0 .. $#routers;
    }
}

## Leer lista de comandos
my @comandos;
{
    open COMANDOS,"<$lista_comandos"
        or die "ERROR: No encuentro $lista_comandos: $!\n";

    chomp ( @comandos = <COMANDOS> );

    close COMANDOS;

    if (DEBUG) {
        print "Comando $_: $comandos[$_]\n" for 0 .. $#comandos;
    }
}

## Para todos los router
foreach my $router ( @routers ) {

 ## Iniciamos la sesión de conexión
    my $sesion = Net::Telnet::Cisco->new;

 ## Ajustamos el modo de error para que sólo nos avise
    $sesion->errmode( sub { warn "$_[0]\n" } );

 ## Probamos la conexión o pasamos al siguiente
    next unless $sesion->open ( $router );
    next unless $sesion->login( $username, $password );

 ## Conectados. Obtenemos el nombre del router
    chomp( my $nombre_router = $sesion->last_prompt );
    print "Conectado a $nombre_router\n"             if DEBUG;

 ## Fecha actual, de ahora mismo, en horario local
    my $fecha = DateTime->now( time_zone => "local" )->datetime;

 ## Nombre del registro de actividad
    $sesion->input_log( "$nombre_router-$fecha.log" );

 ## Envío de los comandos
    foreach my $comando ( @comandos ) {
        my @salida = $sesion->cmd( $comando);
        print "\t$comando\n\t\t@salida\n"            if DEBUG;
    }

 ## Cerramos la sesión
    $sesion->close;
}
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4
(no probado)

NotaPublicado: 2006-09-18 11:30 @521
por explorer
Supongamos que tenemos todo el texto devuelto por el router en la variable $r. Luego entonces, podemos borrar lo indeseable si sabemos qué es lo indeseable.

Por lo que pones, el router muestra ' --More-- ' más un conjunto más o menos largo de espacios en blanco y caracteres "\010", que es el backspace o retroceso. De esa manera, en una terminal, esos caracteres hacen 'desaparecer' el 'More' anterior. Y luego sigue el resto de la línea.

Bien, si estamos seguros que eso es lo indeseable, lo siguiente nos lo filtra:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$r =~ s/^ --More--[\010 ]+(?! )//mg;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

El extraño '(?! )' nos ayudará a guardar el espacio en blanco que SÍ pertenece al resto de la línea, como es el caso de la línea que pone ' rd 14534:10'.

NotaPublicado: 2006-09-18 12:17 @553
por explorer
No lo has entendido. Si haces un more en el linux, no verás estos caracteres, pero ESTÁN. Debes de quitarlos ANTES de pasarlos por el FTP. El FTP no 'mete' ningún carácter extra.

Para verles en el linux, puedes probar a cargar el mensaje en un editor de textos tipo joe o hacer un volcado hexadecimal con el hexdump o con el khexedit. Y con el filtro anterior, lo quitarás, antes de pasarlos por FTP y que los Windows vean cosas 'raras'.

NotaPublicado: 2006-09-18 16:24 @725
por explorer
Esa no es manera de filtrar un array.
Pon esto:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
@salida = $sesion->cmd($tabla_comandos[$y]);
$salida = join('',@salida);
$salida =~ s/^ --More--[\010 ]+(?! )//mg;
print $salida;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

NotaPublicado: 2006-09-18 17:43 @780
por explorer
Pues lo que está pasando es que está fallando la expresión regular...

Prueba a cambiarla por s/ --More--\W+(?! )//mg;

NotaPublicado: 2006-09-19 16:01 @709
por explorer
Pues la verdad, no lo sé... en tu mensaje anterior me faltaría ver la $salida.

Tendrás que empezar a usar las opciones de log para saber qué ocurre.

NotaPublicado: 2006-09-19 17:27 @769
por explorer
Pues no sé lo que pasa... con la expresión regular '$salida =~ s/ --More--\W+(?! )//g;' me funciona bien... (el modificador '/m' no es necesario).

Haz un print $salida justo antes de la expresión regular, y luego, el que tienes puesto ahora, después.

Carga el resultado en un editor de textos y mira a ver si el resultado ha filtrado o no a esos caracteres.

Consulta

NotaPublicado: 2007-01-31 22:53 @995
por colopez
Explorer, una consulta, fíjate que estoy utilizando el script que pusiste acá como ejemplo, haciéndole unos cambios, ya que lo que necesito es configurar N equipos y para esto me esta sirviendo tu script, ya modificado. El tema es que necesito guardar todo lo que hace el programa en un archivo de texto, para que quede constancia de los comandos enviados. Ya probé con el dump_log y sí me guarda el log pero como sabrás hay muchas personas que no se acostumbran a leer este log, también con el $sesion->output_log('debug.log'); pero con este último me da el problema que, como son N equipos, no me guarda todo el log sino únicamente los comandos del último equipo al que se conectó, de antemano agradezco tu valiosa ayuda.