2010-06-29 25 views
7

Estoy luchando con el clásico problema de escribir la contraseña automáticamente en ssh, y al igual que todos los demás estoy dando tumbos en la oscuridad con respecto a lo esperado. Por último, me armó un guión que funciona un poco:exit expect {} sin tiempo de espera

#!/usr/bin/expect -f 

# command line args 
set user_at_host [lrange $argv 0 0] 
set password [lrange $argv 1 1] 

set timeout 1 

# ssh command 
spawn ssh -S ~/.ssh/tmp.$user_at_host -M -N -f $user_at_host 

# deal with ssh prompts 
expect { 
    "*yes/no*" { send "yes\r" ; exp_continue } 
    "*assword:" { send "$password\r" ; exp_continue } 
} 

Este script termina sólo gracias a la línea timeout 1, sin él simplemente se cuelga, y terminará solamente por la interacción del usuario (^C).

Cuando la línea spawn era un comando ssh directo, el script finalizó de inmediato, sin embargo, esto es not your straight forward ssh. Lo que podría ser diferente es la opción -f que lo hace funcionar en segundo plano (pero probé el script sin él en vano).

leí que interact o expect eof podría ayudar, pero no fue capaz de encontrar el encantamiento correcto que en realidad lo hará.

Mi pregunta (creo) es ¿Cómo hacer que un script esperado, que genere un proceso en segundo plano, termine sin tiempo de espera?


Editar: que debería haber esperado (sin doble sentido) la respuesta "utilizar la autenticación SSH sin contraseña". Si bien este es un buen consejo, no es la solución adecuada en mi escenario: probar automáticamente un sistema instalado de vanilla en un entorno confiable, donde agregar claves de confianza a la imagen no es deseable/posible.

Respuesta

1

OK, así que encontró una permutación que parecen funcionar -

Primero necesito un script wrapper que le dará una indicación cuando se hace:

#!/bin/bash 
"[email protected]" 
echo "done" 

A continuación, el script de esperar que se convierte en:

#!/usr/bin/expect -f 
set user_at_host [lrange $argv 0 0] 
set password [lrange $argv 1 1] 

# no need for timeout 1 
set timeout 60 

# use the wrapper 
spawn wrapper ssh -S ~/.ssh/tmp.$user_at_host -M -N -f $user_at_host 

expect { 
    "*yes/no*" { send "yes\r" ; exp_continue } 
    "*assword:" { send "$password\r" ; exp_continue } 
    # use the wrapper 
    "done" { exit } 
} 

Gracias por Douglas Leeder (votado) y glenn jackman (votado) por el útil consejo. Estaré encantado de no aceptar esta respuesta, y aceptaré una respuesta más elegante, tal vez una que elimine el script de envoltura.

Gracias a todos por su atención.

1

Este bucle:

expect { 
    "*yes/no*" { send "yes\r" ; exp_continue } 
    "*assword:" { send "${password}\r" ; exp_continue } 
} 

No se puede terminar cualquier forma, excepto el tiempo de espera o EOF; las dos líneas coincidentes serán exp_continue, así que haz nuevamente el ciclo.

Ir al fondo significa básicamente bifurcación; el padre muere y el niño continúa la conexión.

Personalmente, me gustaría resolver los elementos interactivos de forma diferente:

  1. Las claves de host: De cualquier conecto una vez manualmente, o insertar la llave directamente en el archivo known_hosts de SSH.
  2. Contraseña: Utilizaría la autenticación de clave privada/pública. Utilice un agente para almacenar la clave o tenga una clave sin contraseña.
+0

¿Hay una manera de salir justo después de '* contraseña:'? Cuando traté de reemplazar el 'exp_continue' con cualquier otra cosa, salió inmediatamente, pero no parecía' enviar' la '$ {contraseña}'. –

+0

¿Quizás un 'sueño 1' o' espera eof' o 'espera'? –

+0

Disculpe por haberlo hecho, pero estoy rezagado, y quizás pueda ayudarme a disminuir el número de permutaciones que tengo que probar: ¿Debería 'esperar eof' /' dormir 1' estar dentro o fuera del 'expect {...} '" lazo "? –

7

es probable que desee:

expect { 
    "*yes/no*" { send "yes\r" ; exp_continue } 
    "*assword:" { send "${password}\r" } 
} 
expect $the_prompt 
send "exit\r" 
expect eof 

ACTUALIZACIÓN

echaba de menos al que está enviando un comando a través de SSH. Creo que todo lo que necesita es la siguiente:

spawn ssh [email protected] foo bar baz 
expect { 
    "*yes/no*" { send "yes\r" ; exp_continue } 
    "*assword:" { send "${password}\r" } 
    eof 
} 

Usted GOLPEARÍA eof cuando el comando foo completa.

+0

Esto no solucionó mi problema, pero me dio una pista importante: necesito algún tipo de aviso cuando haya terminado. Ver mi propia respuesta. Gracias. –

0

la forma en que lo hice:

set user "****"  
set host "127.0.0.1"  
spawn shh [email protected]$host  
expect "password: "  
send "**??54"  
expect "$"  
interact 

(eso responde a su cómo utilizar el método interactúan)

Cuestiones relacionadas