2010-06-29 3 views
7

Je suis aux prises avec le problème classique de saisie automatique du mot de passe dans ssh, et comme tout le monde je trébuche dans l'obscurité concernant s'attendre. Enfin, je bricolé un script qui fonctionne un peu:exit Attendez-vous {0 sans timeout

#!/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 } 
} 

Ce script se termine que grâce à la ligne timeout 1, sans elle, il se bloque tout simplement, et prendra fin que par l'interaction utilisateur (^C). Lorsque la ligne spawn était une commande ssh simple, le script s'est terminé immédiatement, mais il s'agit de not your straight forward ssh. La chose qui pourrait être différente est l'option -f qui la fait fonctionner en arrière-plan (mais j'ai essayé le script sans succès). J'ai lu que interact ou expect eof pourrait aider, mais je n'ai pas pu trouver l'incantation correcte qui le fera réellement.

Ma question (je pense) est Comment faire un script attendu, qui engendre un processus d'arrière-plan, se terminer sans un délai?


Edit: Je serais attendu (sans jeu de mots) la réponse "utiliser l'authentification ssh passwordless". Bien que ce soit un bon conseil, ce n'est pas la solution appropriée dans mon scénario: Test automatique d'un système installé dans un environnement de confiance, où l'ajout de clés fiables à l'image n'est pas souhaitable/possible.

Répondre

1

OK, donc je l'ai trouvé une permutation qui semblent fonctionner -

D'abord je besoin d'un script wrapper qui donnera une indication lorsque vous avez terminé:

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

Ensuite, le script expect devient:

#!/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 } 
} 

Merci pour Douglas Leeder (voté) et glenn jackman (voté) pour le conseil utile. Je n'accepterai pas volontiers cette réponse, et j'accepterai une réponse plus élégante, peut-être une qui élimine le script d'encapsulation.

Merci à tous pour votre attention.

1

Cette boucle:

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

Impossible mettre fin à toute façon, sauf délai d'attente ou EOF; les deux lignes correspondantes vont exp_continue, refaire ainsi le tour de la boucle. Passer en arrière-plan signifie fondamentalement forking; le parent meurt, et l'enfant continue la connexion.

Personnellement, je résous les éléments interactifs différemment:

  1. clés de l'hôte: Soit connecter une fois manuellement ou insérer directement la clé dans le fichier known_hosts ssh. Mot de passe: J'utiliserais l'authentification par clé privée/publique. Utilisez un agent pour stocker la clé ou utilisez une clé sans mot de passe.
+0

est-il un moyen de sortir juste après '* mot de passe:'? Quand j'ai essayé de remplacer le 'exp_continue' avec quelque chose d'autre, il a immédiatement quitté, mais n'a pas semblé' envoyer 'le '$ {mot de passe}'. –

+0

Peut-être un «sommeil 1» ou «attendre eof» ou «wait»? –

+0

Je suis désolé de l'avoir fait, mais je traîne, et peut-être pouvez-vous m'aider à diminuer le nombre de permutations que je dois tester: Devrait-il y avoir 'wait eof' /' sleep 1' à l'intérieur ou à l'extérieur de 'expect {...} '" boucle "? –

7

Vous voulez probablement:

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

MISE À JOUR

J'ai raté que vous envoyez une commande via ssh. Je pense que tout ce que vous avez besoin est ceci:

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

Vous seriez frappé eof lorsque la commande foo complète.

+0

Cela n'a pas résolu mon problème, mais m'a donné un indice important: J'ai besoin d'une sorte d'invite une fois terminé. Voir ma propre réponse. Merci. –

0

la façon dont je l'ai fait:

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

(qui répond à votre façon d'utiliser la méthode Interact)