2009-10-08 11 views
17

Ho bisogno di automatizzare la registrazione in una sessione TELNET utilizzando aspettarsi, ma devo occuparmi di più password per lo stesso nome utente.Utilizzo di istruzioni condizionali all'interno di 'expect'

Ecco il flusso ho bisogno di creare:

  1. Aperto sessione Telnet a un IP
  2. Invia nome utente
  3. Invia password
  4. Password errata? Invia lo stesso nome utente di nuovo, quindi una password diversa
  5. necessario accedere-in con successo a questo punto ...

Per quello che vale, ecco quello che ho finora:

#!/usr/bin/expect 
spawn telnet 192.168.40.100 
expect "login:" 
send "spongebob\r" 
expect "password:" 
send "squarepants\r" 
expect "login incorrect" { 
    expect "login:" 
    send "spongebob\r" 
    expect "password:" 
    send "rhombuspants\r" 
} 
expect "prompt\>" { 
    send_user "success!\r" 
} 
send "blah...blah...blah\r" 

Inutile dire che questo non funziona, e non sembra molto bello. Dalle mie avventure con Google aspettarsi sembra essere qualcosa di un'arte oscura. Grazie in anticipo a chiunque per l'assistenza in materia!

+0

Ho aggiunto più informazioni alla mia risposta. – tvanfosson

risposta

31

Devono raccomandare il libro Exploring Expect per tutti i programmatori attesi - inestimabili.

Ho riscritto il codice: (non testato)

proc login {user pass} { 
    expect "login:" 
    send "$user\r" 
    expect "password:" 
    send "$pass\r" 
} 

set username spongebob 
set passwords {squarepants rhombuspants} 
set index 0 

spawn telnet 192.168.40.100 
login $username [lindex $passwords $index] 
expect { 
    "login incorrect" { 
     send_user "failed with $username:[lindex $passwords $index]\n" 
     incr index 
     if {$index == [llength $passwords]} { 
      error "ran out of possible passwords" 
     } 
     login $username [lindex $passwords $index] 
     exp_continue 
    } 
    "prompt>" 
} 
send_user "success!\n" 
# ... 

exp_continue loop di nuovo all'inizio del blocco si aspettano - è come una dichiarazione "rifare".

noti che send_user termina con \n non \r

Non è necessario per sfuggire al carattere > nel prompt: non è speciale per Tcl.

-1

Se si conoscono gli ID utente e le password, è inoltre necessario sapere quali coppie di utenti/password sono allineate con i sistemi. Penso che faresti meglio a mantenere una mappa di quale coppia userid/password va con quale sistema quindi estraendo tali informazioni e semplicemente usa quella corretta.

Quindi, poiché ovviamente non ti piace il mio consiglio, ti suggerisco di guardare lo wikipedia page e di implementare una procedura che restituisca 0 se ha esito positivo e 1 se l'aspettativa è scaduta. Ciò ti consentirà di rilevare quando la password fornita non è riuscita - l'attesa del prompt scade - e riprovare. Se questo è utile, puoi rimuovere il tuo downvote ora che l'ho modificato.

In retrospettiva, si vorrebbe probabilmente farlo in collaborazione con la mappa in ogni caso poiché si vorrebbe rilevare un login fallito se la password è stata cambiata.

+0

Ci scusiamo per il downvote.Avevo una lunga telefonata e volevo un modo rapido per dimostrare che non avevo ancora una risposta senza scrivere un post per spiegare perché. Ad ogni modo, di sicuro non utilizzerei il metodo condizionale se avessi un modo affidabile di documentare le password utilizzate su determinati dispositivi. Può cambiare le revisioni del firmware al di fuori del mio controllo, quindi tutto quello che posso fare è avere un elenco di password pronte per essere provate. Capisco cosa devo fare - usare una dichiarazione condizionale e agire sulla risposta - proprio non so come farlo. :) – shuckster

+0

Puoi rimuovere il voto ora che ho modificato, ovvero se le informazioni aggiuntive sono utili o almeno non rendono il messaggio inutile. Finché non si accetta una risposta, è probabile che le persone continuino ad aggiungere risposte, sebbene si desideri aggiornare la domanda con le informazioni sul perché è difficile tenere traccia delle password. – tvanfosson

10

Con un po 'di colpi ho trovato una soluzione. Risulta che si aspettano utilizza una sintassi TCL che io non sono affatto a conoscenza:

#!/usr/bin/expect 
set pass(0) "squarepants" 
set pass(1) "rhombuspants" 
set pass(2) "trapezoidpants" 
set count 0 
set prompt "> " 
spawn telnet 192.168.40.100 
expect { 
    "$prompt" { 
    send_user "successfully logged in!\r" 
    } 
    "password:" { 
    send "$pass($count)\r" 
    exp_continue 
    } 
    "login incorrect" { 
    incr count 
    exp_continue 
    } 
    "username:" { 
    send "spongebob\r" 
    exp_continue 
    } 
} 
send "command1\r" 
expect "$prompt" 
send "command2\r" 
expect "$prompt" 
send "exit\r" 
expect eof 
exit 

Speriamo che questo sarà utile ad altri.

+1

Ho usato una soluzione simile per SSH ma leggo le password da un file di password '~/.ssh/ssh-password'. Il nome host e il nome utente vengono letti dal mio file '~/.ssh/config'. Così in esecuzione: '[cssh] (https://github.com/DavidGamba/bin/blob/master/cssh) server1' si espanderà a [email protected] – DavidG

+0

Sono nuovo per Aspettarsi, l'aspettativa {"caso1 "{...}" case2 "{...}" case3 "{...}}, si tratta di una sorta di istruzione switch case come C++? grazie –

+0

@ B.Mr.W. si, usandolo all'esterno '' '{}' '' fondamentalmente lo fa cadere invece delle singole dichiarazioni '' if''' – eulerworks