Script para ejecutar comandos automaticamente via Telnet o SSH

By Published On: 19 de octubre de 2012Categories: GNU-Linux, Programacion, Redes0 Comments

Si queremos conectarnos a un equipo ya sea via Telnet o SSH y ejecutar un conjunto de comandos especificos o capturar alguna información de este dispositivo de forma automatica, el siguiente script que encontre en el Wiki de Cisco les va a ayudar muchisimo.

El Script esta hecho en Expect (Expect en Wikipedia), por lo cual vamos a necesitar instalar el paquete expect («yum install expect») para poder correr el script.
Luego de tener expect instalado, procedemos a generar un archivo con el siguiente contenido:

#!/usr/bin/expect --
##########################################################################
# vty_runcmd.exp
#
# This is an expect script that will connect to a device using ssh or
# telnet, then run the specified command. The output will either be
# written to an output file or printed to stdout.
#
# Created by Tim Evens ([email protected]), 5/2009
# Corrected by Sergio Zavala (sergio.zavala at sidetec.com.mx), 12/2010
#
# Copyright Tim Evens, 2009
#
# HISTORY:
# Tim Evens 5/21/09 Initial program created
# Sergio Zavala 12/26/10 Connection return code corrected
# Tim Evens 1/05/10 Connection validated
##########################################################################

#++++++++++++++++++++++++++
# Global vars
#++++++++++++++++++++++++++
set timeout 30
# below matches prompts such as "router#", "router>", "router$"
set prompt "> *$|# *$|\$ *$"


#-----------------------------------------------
# Connect(method, prompt, host, user, password)
# This function will connect to a host using telnet or ssh.
#
# RETURNS:
# zero if successful
# 1 = timeout or invalid hostname or method
# 2 = invalid login
# 3 = timeout waiting for login
# 4 = connection failed to host during expect wait
# 9 = unknown error
#-----------------------------------------------
proc Connect {method host usr pw} {
set rval 0
set usr_chk 0
set pw_chk 0
set max_checks 4
global spawn_id
global timeout
global prompt

puts "Connecting using $method to $host as user $usr"

# see if we are using ssh
if {
[string compare $method "ssh"] == 0 } {
set host "$usr@$host"
}

# Run command and get connected
set id [spawn $method $host] if { $id <= 0 } {
puts "ERROR: Failed to connect to hostn"
set rval 1

} else {
puts "Using Process ID: $id"
}

# Start the expect/send process to login
expect {

# Below handles the username prompt
-nocase -re "name:|^login:" {
send "$usrr"
incr usr_chk;

# continue with expect loop as long as we haven't hit this too many times
if { $usr_chk < $max_checks } {
exp_continue
} else {
set rval 2
puts "ERROR: Login retry failed. Invalid login username"
}

# Below handles the password prompt
} -nocase -re "word:" {
send "$pwr"
incr pw_chk;

# continue with expect loop as long as we haven't hit this too many times
if { $pw_chk < $max_checks } {
exp_continue
} else {
set rval 2
puts "ERROR: Login retry failed. Invalid login password"
}

# Below handles the yes/no prompt when SSH first connects to a host
} -nocase -re "(yes/no)" {
send "yesr"
exp_continue

# Below handles the normal prompt to detect when logged in
} -nocase -re "$prompt" {
puts "nSUCCESS: Logged in and ready to send commandsn"

# Below is for expect timeout waiting for a
} timeout {
puts "ERROR: Connection timeout waiting for login prompt"
set rval 3

# Below is for when the connect is closed before finishing
} eof {
puts "ERROR: Connection to host failed: $expect_out(buffer)"
set rval 4
}
}

# return with error code
return $rval
}
# End of Connect ()

#-----------------------------------------------
# Usage()
# This function will print the usage
#-----------------------------------------------
proc Usage {} {

puts "Usage: vty_runcmd.exp <options>"
puts "n"
puts "REQUIRED OPTIONS:"
puts " -h <hostname|ip> = hostname or ip address"
puts " -u <username> = username to login with"
puts " -p <password> = password for login"
puts "n"
puts "Other OPTIONS:"
puts " -e <enable password> = Enable password"
puts " -t <seconds> = timeout in seconds"
puts " -m <ssh|telnet> = use either ssh or telnet, default telnet"
puts " -f <filename> = command file, defaults to STDIN"
puts "n"
}
# End of Check_ARGS()

#-----------------------------------------------
# main()
#
# RETURNS:
# 0 if successful
# 1 if invalid arg passed
# 2 not enough args (required args not met)
#-----------------------------------------------
set rval 0
set hostname ""
set username ""
set password ""
set enable_pw ""
set cmdfile ""
set method "telnet"

# Loop through the command line args
for {set n 0} {$n < $argc} {incr n} {

set arg [lindex $argv $n]
# Check the args
if { [string compare $arg "-u"] == 0} {
if { $n < $n+1 } {
incr n
set username [lindex $argv $n] } else {
set rval 1
puts "ERROR: Missing ARG for $argn"
}

} elseif { [string compare $arg "-p"] == 0} {
if { $n < $n+1 } {
incr n
set password [lindex $argv $n] } else {
set rval 1
puts "ERROR: Missing ARG for $argn"
}

} elseif { [string compare $arg "-h"] == 0} {
if { $n < $n+1 } {
incr n
set hostname [lindex $argv $n] } else {
set rval 1
puts "ERROR: Missing ARG for $argn"
}

} elseif { [string compare $arg "-m"] == 0} {
if { $n < $n+1 } {
incr n
set method [lindex $argv $n] } else {
set rval 1
puts "ERROR: Missing ARG for $argn"
}

} elseif { [string compare $arg "-t"] == 0} {
if { $n < $n+1 } {
incr n
set timeout [lindex $argv $n] } else {
set rval 1
puts "ERROR: Missing ARG for $argn"
}

} elseif { [string compare $arg "-f"] == 0} {
if { $n < $n+1 } {
incr n
set cmdfile [lindex $argv $n] } else {
set rval 1
puts "ERROR: Missing ARG for $argn"
}

} elseif { [string compare $arg "-e"] == 0} {
if { $n < $n+1 } {
incr n
set enable_pw [lindex $argv $n] } else {
set rval 1
puts "ERROR: Missing ARG for $argn"
}
}
}
# End of arg check

# make sure we found the amount of args expected
if { [llength $hostname] > 0 && [llength $method] > 0 &&
[llength $username] > 0 && [llength $password] > 0 } {
# Print out the args found
puts "hostname = $hostname, user = $username, pw = $password, method = $method"

} else {
set rval 2
puts "ERROR: Missing required args, must have -h, -u, -pn"
Usage
}

# ------------------
# Now that we have the correct ARGS and we know what to do, lets proceed to
# connect, run the commands, then exit.
# ------------------

# make sure we have not encountered any errors
if { $rval <= 0 } {

if { [llength $cmdfile] <= 0 } {
puts "Enter the send text (type 'end' on last line to finish):"
expect_user -nocase -re "(.*)nendn"
set send_text $expect_out(1,string)

} else {
puts "Using $cmdfile for send text"
# set cmdfile_fd [open $cmdfile r] if { [catch {set cmdfile_fd [open $cmdfile r]} err_msg] } {
puts stderr "Could not open $cmdfile for readingn$err_msg"
exit 1
}

# read in the file info - warning there is a limit on the size
set send_text [read $cmdfile_fd 10000]
# close open file
close $cmdfile_fd
}

# connect and check return status before proceeding
if { [Connect "$method" "$hostname" "$username" "$password"] > 0 } {
# stop here, no need to print an error since Connect func does that
exit 1
}


# If we have an enable password, lets try to send it
if { [llength $enable_pw] > 0} {
puts "***Using enable mode"
send "enabler"
expect {
-timeout 3
# Below handles the password prompt
-nocase -re "word:" {
send "$enable_pwr"
exp_continue

# Below handles the normal prompt to detect when logged in
} -re "# *$" {
puts "--SUCCESS on enable mode--"

# Below is for expect timeout waiting for a
} timeout {
puts "ERROR: Enable password timeout"
set rval 3

# Below is for when the connect is closed before finishing
} eof {
puts "ERROR: Connection to host failed: $expect_out(buffer)"
set rval 4
}
}
}

# Loop through the send_text and send one line at a time
foreach line [split $send_text n] {
# Make sure to exclude empty lines
if { [llength $line] > 0 } {
send "$liner"

# Start the expect/send process to login
expect {
# Below handles the yes/no prompts
-nocase -re "(yes/no)" {
send "yesr"
exp_continue

# Below handles the y/n prompts
} -nocase -re "(yes/no)" {
send "yesr"
exp_continue

# Below handles the y/n prompts
} -nocase -re "--more--" {
send " "
exp_continue

# Below handles the normal prompt to detect when logged in
} -nocase -re "$prompt" {
puts "n--SUCCESS for normal login prompt--n"
}
}

}
}

# Now that we are done, send an exit
puts "*** Finished with script"
send "exitr"
sleep 1
}

## END OF SCRIPT #############################################################

Guardamos el archivo y le damos permisos de ejecución:
[ root@punto-libre ]# chmod +x script-vty
Las opciones que permite el script son las siguientes:
-u   =   Nombre de usuario
-p   =   Contraseña del usuario
-e   =   Contraseña de enable (Para equipos cisco)
-m  =   Metodo de conexion, puede ser telnet o ssh.
-f    =   Archivo que contendra los comandos a ejecutar.
La sintaxis para usar el script seria la siguiente:
[ root@punto-libre ]# ./script-vty -h 10.0.0.1 -u usuario -p claveusuario -e claveenable -m (ssh o telnet) -f comandos.text
Ya con esto las posibilidades son infinitas, podemos utilizar este script dentro de otro creado por nosotros y que se adapte a nuestras necesidades, luego les compartire algunos ejemplos de lo que podran realizar y actualizo el articulo.

Leave A Comment