Buenas tardes, colegas.
Estoy trabajando en un
script que se ha vuelto bastante engorroso, contaré la historia corta y luego expondré mi problema.
Actualmente uso Perl para conectarme y extraer información de equipos de red (
switches y
routers) por ahora Juniper y Cisco, la conexión a estos equipos se hace vía Telnet, lo ideal sería que se hiciera la conexión por SSH, y pues bien es aquí donde está mi problema.
Aproximadamente manejo unos 70
scripts hechos en Perl que se encargan de realizar diferentes actividades sobre los equipos de red. Entre estas actividades, por nombrarles algunas, están: ejecutar comandos para actualizar ancho de banda, cambios de
vlan, cambios de interfaces, cambio de descripción del servicio en una interfaz específica,
backups de los equipos de red, etc.
Como pueden observar son bastantes actividades, ahora bien, estas actividades las realiza conectándose por medio de los módulos
Net::Telnet y
Net::Telnet::Cisco. En principio resolví que tal vez solo era necesario cambiar la forma en que se conecta a los equipos y el resto funcionaría normal pero no ha sido así.
El problema radica en que decidí usar el módulo
Net::OpenSSH el cual corresponde a realizar acciones usando SSH. Luego de leer bastante este foro decidí usarlo porque me pareció más sencillo de aplicar. La solución la apliqué a los equipos Juniper y algunos de los
scripts corren sin problemas ya que no he terminado de probar los demás, pero con los Cisco estoy teniendo inconvenientes. La verdad quiero ahorrarme el trabajo de editar uno a uno los
scripts, ya que me tardaría bastante tiempo y no es la idea.
A continuación los ejemplos de lo que estoy usando para realizar esta actividad y el problema que se me presenta:
(Por cierto este
script es muy cortito y solo quiero realizar la prueba de conectarme y ejecutar los comandos; por ello no es tan extenso como los demás).
Primero, una librería hecha por mi para realizar la conexión por SSH. (En realidad tiene más funciones pero me enfocaré en explicar únicamente la que tiene mi problema):
Para conexión por SSH se usa:
Using perl Syntax Highlighting
sub conectar_ssh{
## ---------------------------------------------------------------
## Inicialización de variables
## ---------------------------------------------------------------
my $ip = $_[0];
my ($stderr) = ('');
$ssh = Net::OpenSSH->new($ip, user => $userbackupsdefault, passwd => $passbackupsdefault);
# $ssh = Net::OpenSSH->new($ip, user => $userbackupsdefault, passwd => 'prueba');
if ($ssh->error) {
$stderr=$ssh->error;
warn "imposible conectar con servidor remoto $ip: ". $ssh->error;
return $stderr, $ssh;
}
$stderr=$ssh->error;
return $stderr, $ssh;
}
sub cerrar_ssh {
my $ssh = $_[0];
$ssh->close();
my $err = $ssh->error;
return $err
}
Coloreado en 0.003 segundos, usando
GeSHi 1.0.8.4
Bien, ese
script solo tiene un problema con los Juniper de lo que he probado, y es que no existe un método
close para cerrar la conexión usando el módulo Net::OpenSSH, pero igual la cierra automáticamente al terminar de ejecutar un comando. Es un problema pequeño, imagino yo. Luego está el
script que estoy usando para ejecutar comandos sobre los equipos; para este caso lo hago sobre un equipo Cisco:
Using perl Syntax Highlighting
#!/usr/bin/perl
use Net::OpenSSH;
require '/usr/local/library/procedimientos_ifx.pl'; #funciones reutilizables
#my $cmd = 'show version'; # El comando a ejecutar
my $host = 'X.X.X.X'; # IP a la que me quiero conectar
my @conn1 = conectar_ssh($host); # Esta función está en procedimientos.pl
#Verifico si me devuelve un error, en caso de serlo genero el mensaje de error recibido y lo muestro en pantalla.
if (($conn1[0])) {
$mensajeerror="Equipo=CiscoN1, IP=$host, Descripcion=$conn1[0]\n<br>";
print "$mensajeerror\n";
}else
{
#Se conecta sin problemas, entonces ejecuto los comandos a continuación
@out=$conn1[1]->capture("enable\n"); # Modo Configuración en Router Cisco.
@out=$conn1[1]->capture("show configuration class-of-service | display set | match interface | no-more\n");
# Por cada Línea que se haya generado asigno su correspondiente respuesta a la variable $salida
foreach $line1 (@out) {
$salida .= "$line1\n";
}
#################################################################
## Esto está comentado porque así funciona para los Juniper ##
## Es decir que si uso solo "capture" el programa falla porque ##
## no va a generar el resultado esperado. ##
#################################################################
#@out=$conn1[1]->system("quit\n");
#@out=$conn1[1]->capture("quit\n");
print "----- $host -----\noutput:\n$salida]\nerror:\n$mensajeerror\n";
}
Coloreado en 0.002 segundos, usando
GeSHi 1.0.8.4
Y bien, al ejecutar este
script la respuesta que obtengo es la siguiente:
Using bash Syntax Highlighting
[root@miServer ~]# /home/user/scripts_pruebas/sshprueba.pl
channel_by_id: 0: bad id: channel free
client_input_channel_req: channel 0: unknown channel
Connection to 10.x.x.x closed by remote host.
Use of uninitialized value in concatenation (.) or string at /home/eherrera/scripts_pruebas/sshprueba.pl line 31.
----- 10.16.124.3 -----
output:
]
error:
0
Coloreado en 0.002 segundos, usando
GeSHi 1.0.8.4
Y no he encontrado manera de quitarle ese problema. Se ha vuelto caótico. Llevo dos días en esto. Espero puedan, por favor, ayudarme en algo que se acomode a esta misma estructura, es decir, una forma de usar este módulo para resolverlo o en dado caso hacer uso de otro módulo que haga ese mismo proceso pero que permita hacer más fácil la modificación masiva de los
scripts.
Quedo atento a sus comentarios e inquietudes.
Saludos,
Jero2528
Bogotá, Colombia