automatizar la sesión de telnet usando scripts bash

80

Estoy trabajando en la automatización de algunas tareas relacionadas con telnet, usando scripts Bash. Una vez automatizado, no habrá interacción del usuario con telnet. (es decir, estará totalmente automatizado)

los scripts se parecen a esto:

# execute some commands on the local system
# access a remote system with an IP address: 10.1.1.1 (for example)

telnet 10.1.1.1

# execute some commands on the remote system
# log all the activity (in a file) on the Local system
# exit telnet
# continue on with executing the rest of the script.

Hay 2 problemas a los que me enfrento aquí:

  1. ¿Cómo ejecutar los comandos en el sistema remoto desde el script (sin interacción humana)?

    De mi experiencia con algunos códigos de prueba, pude deducir que cuando se ejecuta telnet 10.1.1.1 , telnet entra en una sesión interactiva y las siguientes líneas de código en el script se ejecutan en el sistema local. ¿Cómo puedo ejecutar las líneas de código en el sistema remoto en lugar del local?

  2. No puedo obtener un archivo de registro de la actividad en la sesión de telnet en el sistema local. La redirección de stdout que utilicé hace una copia en el sistema remoto (no quiero realizar una operación de copia para copiar el registro en el sistema local). ¿Cómo puedo lograr esta funcionalidad?

kan
fuente

Respuestas:

77

Escribe un expectguión.

Aquí hay un ejemplo:

#!/usr/bin/expect

#If it all goes pear shaped the script will timeout after 20 seconds.
set timeout 20
#First argument is assigned to the variable name
set name [lindex $argv 0]
#Second argument is assigned to the variable user
set user [lindex $argv 1]
#Third argument is assigned to the variable password
set password [lindex $argv 2]
#This spawns the telnet program and connects it to the variable name
spawn telnet $name 
#The script expects login
expect "login:" 
#The script sends the user variable
send "$user "
#The script expects Password
expect "Password:"
#The script sends the password variable
send "$password "
#This hands control of the keyboard over to you (Nice expect feature!)
interact

Correr:

./myscript.expect name user password
joemooney
fuente
2
el "esperar" es principalmente para sesiones interactivas. Lo que quiero es una sesión automatizada no interactiva. el problema al que me enfrento es que no puedo ejecutar los scripts en el sistema remoto (a través de telnet) ya que todas las líneas que siguen a telnet 10.1.1.1 se ejecutan en la máquina local en lugar de en la máquina a la que estoy accediendo.
khan
3
Como señaló Thomas Telensky, dependiendo de sus necesidades, ssh es, en última instancia, más fácil. Pero esperar puede ser completamente no interactivo. Supongo que quiere decir que todas las líneas que siguen a telnet son las que desea que se ejecuten en la máquina remota, en ese caso, simplemente agréguelas al script de espera como comandos de envío y elimine el comando de interacción. Pero ssh es más fácil y seguro.
joemooney
2
lo suficientemente justo. Usaré esperar para esta tarea.
khan
1
otra buena adición es leer esto - elenako.com/2013/04/04/… , siempre que el script no haya tenido una \rsecuencia al final del comando, y cuando hice clic en Enter, no funcionó por alguna razón
llamerr
88

Si bien sugeriría usar esperar también, para un uso no interactivo, los comandos de shell normales podrían ser suficientes. Telnet acepta su comando en stdin, por lo que solo necesita canalizar o escribir los comandos en él:

telnet 10.1.1.1 <<EOF
remotecommand 1
remotecommand 2
EOF

(Editar: a juzgar por los comentarios, el comando remoto necesita algo de tiempo para procesar las entradas o el SIGHUP temprano no es tomado con elegancia por telnet. En estos casos, puede intentar una breve suspensión en la entrada :)

{ echo "remotecommand 1"; echo "remotecommand 2"; sleep 1; } | telnet 10.1.1.1

En cualquier caso, si se está volviendo interactivo o algo así, use expect.

thiton
fuente
2
+1 sleepfunciona como un sueño ;-) También agregué algo | tee /dev/tty |intermedio para tener una sesión completa en la pantalla ;-)
paluh
1
en mi caso, la respuesta más útil, pero tuve que agregarecho -e "command\r";
mf_
1
¿Cómo proporciono una contraseña a telnet de forma no interactiva?
Geremia
{ echo "remotecommand 1"; echo "remotecommand 2"; sleep 1; } | telnet 10.1.1.1 : Este ejemplo cumple con mis requisitos. Solo quiero saber cómo agregamos la verificación de errores si telnet falla y el script de shell debería hacerlo exit 1.
Yash
44

Telnet se usa a menudo cuando aprende el protocolo HTTP. Solía ​​usar ese script como parte de mi raspador web:

echo "open www.example.com 80" 
sleep 2 
echo "GET /index.html HTTP/1.1" 
echo "Host: www.example.com" 
echo 
echo 
sleep 2

digamos que el nombre del script es get-page.sh y luego:

get-page.sh | telnet

le dará un documento html.

Espero que sea de ayuda para alguien;)

biera
fuente
1
¡El comentario más útil! En realidad, esto le permite automatizar el envío de comandos colocándolos en un bucle
RomanM
Otra publicación de ayuda blog.tonycode.com/tech-stuff/http-notes/…
leomeurer
De una sola línea equivalente: { echo "GET / HTTP/1.1"; echo "Host: www.example.com"; echo; sleep 1; } | telnet www.example.com 80. Tenga en cuenta que la suspensión no es necesaria al principio (a menos que use el comando de apertura) y que solo se necesita un eco vacío y la suspensión 1 en lugar de 2 al final.
baptx
Pero si necesita hacer solicitudes HTTPS, debe usar netcat, también conocido como ncat o nc:{ echo "GET / HTTP/1.1"; echo "Host: example.com"; echo; sleep 1; } | ncat --ssl example.com 443
baptx
12

Esto funcionó para mí ...

Estaba intentando automatizar varios inicios de sesión de telnet que requieren un nombre de usuario y una contraseña. La sesión de telnet debe ejecutarse en segundo plano de forma indefinida, ya que estoy guardando registros de diferentes servidores en mi máquina.

telnet.sh automatiza el inicio de sesión de telnet usando el comando 'esperar'. Puede encontrar más información aquí: http://osix.net/modules/article/?id=30

telnet.sh

#!/usr/bin/expect
set timeout 20
set hostName [lindex $argv 0]
set userName [lindex $argv 1]
set password [lindex $argv 2]

spawn telnet $hostName

expect "User Access Verification"
expect "Username:"
send "$userName\r"
expect "Password:"
send "$password\r";
interact

sample_script.sh se utiliza para crear un proceso en segundo plano para cada una de las sesiones de telnet ejecutando telnet.sh. Se puede encontrar más información en la sección de comentarios del código.

sample_script.sh

#!/bin/bash
#start screen in detached mode with session-name 'default_session' 
screen -dmS default_session -t screen_name 
#save the generated logs in a log file 'abc.log' 
screen -S default_session -p screen_name -X stuff "script -f /tmp/abc.log $(printf \\r)"
#start the telnet session and generate logs
screen -S default_session -p screen_name -X stuff "expect telnet.sh hostname username password $(printf \\r)"
  1. Asegúrese de que no se esté ejecutando ninguna pantalla en el fondo mediante el comando 'screen -ls'.
  2. Lea http://www.gnu.org/software/screen/manual/screen.html#Stuff para leer más sobre la pantalla y sus opciones.
  3. La opción '-p' en sample_script.sh preselecciona y vuelve a adjuntar a una ventana específica para enviar un comando a través de la opción '-X'; de lo contrario, aparece el error 'No se encontró sesión de pantalla'.
Nikhil
fuente
2

Puede utilizar los scripts de espera instalados en bash. El siguiente ejemplo muestra cómo hacer telnex en una placa incorporada que no tiene contraseña

#!/usr/bin/expect

set ip "<ip>"

spawn "/bin/bash"
send "telnet $ip\r"
expect "'^]'."
send "\r"
expect "#"
sleep 2

send "ls\r"
expect "#"

sleep 2
send -- "^]\r"
expect "telnet>"
send  "quit\r"
expect eof
Arkansas
fuente
2

Lo siguiente está funcionando para mí ... coloque todas sus IP que desea telnet en IP_sheet.txt

while true
read a
do
{
    sleep 3
    echo df -kh
    sleep 3
    echo exit
} | telnet $a
done<IP_sheet.txt
SAEED MAHMOOD ASLAM
fuente
1
#!/bin/bash
ping_count="4"
avg_max_limit="1500"
router="sagemcom-fast-2804-v2"
adress="192.168.1.1"
user="admin"
pass="admin"

VAR=$(
expect -c " 
        set timeout 3
        spawn telnet "$adress"
        expect \"Login:\" 
        send \"$user\n\"
        expect \"Password:\"
        send \"$pass\n\"
        expect \"commands.\"
        send \"ping ya.ru -c $ping_count\n\"
        set timeout 9
        expect \"transmitted\"
        send \"exit\"
        ")

count_ping=$(echo "$VAR" | grep packets | cut -c 1)
avg_ms=$(echo "$VAR" | grep round-trip | cut -d '/' -f 4 | cut -d '.' -f 1)

echo "1_____ping___$count_ping|||____$avg_ms"
echo "$VAR"
chamán888
fuente
0

Utilice ssh para ese propósito. Genere claves sin usar una contraseña y colóquelas en .authorized_keys en la máquina remota. Cree el script para ejecutarlo de forma remota, cópielo en la otra máquina y luego ejecútelo de forma remota usando ssh.

Usé este enfoque muchas veces con gran éxito. También tenga en cuenta que es mucho más seguro que telnet.

TMS
fuente
1
sshes seguramente más seguro que telnet, pero algunos dispositivos IP simplemente no brindan sshservicio y dependen del telnetprotocolo para usar el dispositivo.
fduff
2
telnet (el programa) se puede utilizar como cliente para CUALQUIER (o más prácticamente la MAYORÍA) de las conexiones cliente / servidor basadas en texto. Se puede utilizar para realizar pruebas sencillas, por ejemplo, HTTP e IMAP. La sugerencia de @Tomas es reemplazar el uso de Telnet (el servicio de inicio de sesión remoto) con SSH. si bien su comentario es cierto, probablemente no sea lo que requería el PO.
Rob Shepherd
Rob, de hecho, telnet se puede usar para conectarse a cualquier puerto, pero vea la pregunta de OP - en su contexto, él quiere usar telnet solo para iniciar sesión (citando: "ejecutar algunos comandos en el sistema remoto" ). Usar telnet para este propósito es muy arriesgado.
TMS
Esta no es una respuesta a la pregunta que dice específicamente 'automatizar algunas tareas relacionadas con telnet' usando sus scripts existentes.
FractalSpace
0

Aquí es cómo usar telnet en bash shell / espera

#!/usr/bin/expect
# just do a chmod 755 one the script
# ./YOUR_SCRIPT_NAME.sh $YOUHOST $PORT
# if you get "Escape character is '^]'" as the output it means got connected otherwise it has failed

set ip [lindex $argv 0]
set port [lindex $argv 1]

set timeout 5
spawn telnet $ip $port
expect "'^]'."
grepit
fuente
0

Script para obtener la versión de los servidores CISCO:

#!/bin/sh

servers='
192.168.34.1
192.168.34.3
192.168.34.2
192.168.34.3
'
user='cisco_login'
pass='cisco_password'

show_version() {
host=$1
expect << EOF
set timeout 20
set host $host
set user $user
set pass $pass
spawn telnet $host
expect "Username:"
send "$user\r"
expect "Password:"
send "$pass\r"
expect -re ".*#"
send "show version\r"
expect -re ".*-More-.*"
send " "
expect -re ".*#"
send "exit\r"
EOF
}

for ip in $servers; do
  echo '---------------------------------------------'
  echo "$ip"
  show_version $ip | grep -A3 'SW Version'
done
AnselmRu
fuente
-4

Juega con tcpdumpo wiresharky mira qué comandos se envían al servidor.

Prueba esto

printf (printf "$username\r\n$password\r\nwhoami\r\nexit\r\n") | ncat $target 23

Algunos servidores requieren un retraso con la contraseña ya que no retiene líneas en la pila

printf (printf "$username\r\n";sleep 1;printf "$password\r\nwhoami\r\nexit\r\n") | ncat $target 23**
str8
fuente
9
La novedad no es excusa para la mala educación. Consulte las preguntas frecuentes stackoverflow.com/faq .
Verbeia
1
no estaba destinado a ser un insulto, más como ... no sé, disculpas. Sigo viendo gente que usa el comando de espera como solución. Solo quiero que la gente se dé cuenta de que hay una mejor solución para comprender lo que está tratando de lograr. El comando de espera no le muestra cómo funciona, es solo una solución para no saberlo. Es más confuso que no. En caso de duda acuda a la fuente. Si la fuente no está disponible, y si se trata de un protocolo de red, tcpdump, wirehark, espíe los paquetes y siga el flujo de comandos y debería poder armar algo con conocimientos prácticos.
str8
7
Si lo dice, soy programador de Mathematica, por lo que la sustancia de su respuesta y comentario es un misterio para mí. Pero no soy el único que interpreta la palabra "idiotas" como un insulto intencional. Creo que necesitas pasar un poco más de tiempo en el sitio y ver cómo se comporta la gente aquí.
Verbeia