2010-06-29 11 views
7

Ich kämpfe mit dem klassischen Problem der Eingabe von Passwort automatisch in ssh, und wie alle anderen stolpere ich im Dunkeln über erwarten. Schließlich gepflasterten ich ein Skript zusammen, die ein bisschen arbeiten:exit expect {} ohne Zeitüberschreitung

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

Dieses Skript endet nur dank der timeout 1 Linie, ohne sie es einfach hängt und wird nur durch Interaktion mit dem Benutzer (^C) beenden.

Wenn die Zeile spawn ein direkter ssh-Befehl war, wurde das Skript sofort beendet, dies ist jedoch not your straight forward ssh. Die Sache, die anders sein könnte, ist die -f Option, die es im Hintergrund laufen lässt (aber ich habe das Skript ohne es vergeblich versucht).

Ich lese, dass interact oder expect eof könnte helfen, aber ich war nicht in der Lage, die richtige Beschwörungsformel zu finden, die es tatsächlich tun wird.

Meine Frage (denke ich) ist Wie kann man ein Expect-Skript erstellen, das einen Hintergrundprozess hervorbringt, der ohne Timeout beendet wird?


Edit: Ich erwartet hätte (kein Wortspiel beabsichtigt), um die "Authentifizierung passwordless ssh" Antwort. Obwohl dies ein guter Rat ist, ist es in meinem Szenario nicht die geeignete Lösung: Automatisches Testen eines in einer Vanilla installierten Systems in einer vertrauenswürdigen Umgebung, wo das Hinzufügen vertrauenswürdiger Schlüssel zum Image nicht wünschenswert/möglich ist.

Antwort

1

OK, so fand ich eine Permutation, die zu funktionieren scheint -

Zuerst habe ich ein wrapper Skript benötigen, die einen Hinweis geben, wenn Sie fertig sind:

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

die dann erwarten Skript wird:

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

Vielen Dank für Douglas Leeder (abgestimmt) und glenn jackman (abgestimmt) für den hilfreichen Rat. Ich werde diese Antwort gerne ablehnen und eine elegantere Antwort akzeptieren, vielleicht eine, die das Wrapper-Skript aufhebt.

Vielen Dank für Ihre Aufmerksamkeit.

1

Diese Schleife:

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

keine Möglichkeit außer Timeout beenden kann oder EOF; die zwei übereinstimmenden Linien werden exp_continue, also runden Sie die Schleife wieder.

In den Hintergrund zu gehen bedeutet grundsätzlich Forking; Der Elternteil stirbt und das Kind setzt die Verbindung fort.

Persönlich würde ich die interaktiven Elemente anders lösen:

  1. Host-Schlüssel: Entweder einmal manuell verbinden, oder den Schlüssel direkt in der ssh known_hosts-Datei einfügen.
  2. Passwort: Ich würde private/öffentliche Schlüssel Authentifizierung verwenden. Verwenden Sie einen Agenten, um den Schlüssel zu speichern, oder verwenden Sie einen kennwortlosen Schlüssel.
+0

Gibt es eine Möglichkeit direkt nach dem '* Passwort zu verlassen:'? Als ich versuchte, das 'exp_continue' durch etwas anderes zu ersetzen, wurde es sofort beendet, schien aber' '{password}' 'nicht zu senden. –

+0

Vielleicht ein "Schlaf 1" oder "erwarten eof" oder "warten"? –

+0

Entschuldigung dafür, dass ich es abgehört habe, aber ich verspringe, und vielleicht kannst du mir helfen, die Anzahl der zu testenden Permutationen zu verringern: Sollte "warten" innerhalb oder außerhalb des 'erwarten {...} "Schleife"? –

7

Sie wollen wahrscheinlich:

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

UPDATE

ich verpasst, dass Sie einen Befehl via ssh senden. Ich denke, dass alles, was Sie brauchen, ist dies:

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

Sie eof treffen würde, wenn der foo Befehl abgeschlossen ist.

+0

Das hat mein Problem nicht gelöst, aber gab mir einen wichtigen Hinweis: Ich brauche eine Art Aufforderung, wenn ich fertig bin. Siehe meine eigene Antwort. Vielen Dank. –

0

die Art, wie ich es tat:

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

(das beantwortet Ihre wie interact Methode verwenden)

Verwandte Themen