2016-02-24 63 views
-1

我寫了一個腳本,通過ssh登錄並運行一些命令。列表中的一半設備列表中有一個可接受的用戶名和密碼組合。循環訪問多個憑據TCL期望

我想希望能夠解釋失敗的登錄,開始用相同的設備新的登錄嘗試,但在第二次嘗試使用不同的登錄憑證(有兩種可能的用戶名和密碼組合)

如果任何人都可以將我指向正確的方向,我真的很感激它。這是我第一次使用TCL或期望。

我到目前爲止的一個縮寫版本如下。

set username "someusername" 
set password "somepassword" 

set devices "X.X.X.X" 

foreach device $devices { 
    puts "Processing device: $device"; 
    spawn plink -ssh $devices 

    expect "Store key in cache" 
    send "y\r" 

    expect "login as:" 
    send "$username\r" 

    expect "password:" 
    send "$password\r" 
    expect "#" 

send "conf t\r" 
expect "(config)#" 

send "some commands\r" 
expect "(config)#" 

send "end\r" 
expect "#" 

send "copy run startup-config\r" 
expect "#" 
+0

你知道嗎'foreach'可以在兩個或多個列表一次迭代? 'foreach device $ devices username $ usernames password $ passwords {...}'。這可以使這種事情更容易... –

+0

我不知道唐納。謝謝!儘管如此,即使這個foreach有不止一個名單,TCL也會在第一次失敗後退出。而且,我連接的思科設備在輸入錯誤密碼後不會再次提示輸入用戶名,所以我認爲除了能夠傳遞多個auth變量集外,腳本還需要能夠啓動一個新的會話使用$ devices中的同一個$設備。我不確定情況如何,只是我的猜測。如果,我不樂意被設置成直線。 – helloworldhello

回答

1

你可能需要像

set usernames [list name1 name2] 
set passwords [list pw1 pw2 ] 

set devices [list X.X.X.X ...] 

foreach device $devices { 
    puts "Processing device: $device"; 
    spawn plink -ssh $devices 

    set auth_idx -1 

    expect { 
     "Store key in cache" {send "y\r"; exp_continue} 

     "login as:" { 
      incr auth_idx 
      if {$auth_idx == [llength $usernames]} { 
       puts "login failed for $device" 

       # close the plink connection. I'm guessing here 
       send \003  ;# Ctrl-C 
       expect eof 

       # and on to the next device 
       continue 
      } 

      send "[lindex $usernames $auth_idx]\r" 
      expect "password:" 
      send "[lindex $passwords $auth_idx]\r" 

      # and wait for either the command prompt or another login prompt 
      exp_continue 
     } 

     "#" 
    } 

    # ... whatever you do when you're logged in 

    # and logout. something like 
    send "quit\r" 
    expect eof 
} 

它使用exp_continue以 「循環」 中同樣預期的語句。我假設你可能並不總是需要將密鑰存儲在緩存中。我還以爲你看到的「登錄爲」如果第一次登錄嘗試失敗


UPDATE

set usernames [list name1 name2] 
set passwords [list pw1 pw2 ] 

set devices [list X.X.X.X ...] 

set device_idx 0 
set auth_idx 0 

while {$device_idx < [llength $devices]} { 
    set device [lindex $devices $device_idx] 

    puts "Processing device: $device"; 
    spawn plink -ssh $devices 

    expect { 
     "Store key in cache" {send "y\r"; exp_continue} 

     "login as:" { 
      send "[lindex $usernames $auth_idx]\r" 
      expect "password:" 
      send "[lindex $passwords $auth_idx]\r" 
      exp_continue 
     } 

     "Access denied" { 
      incr auth_idx 
      if {$auth_idx == [llength $usernames]} { 
       puts "login failed for $device" 
       # next device 
       set auth_idx 0 
       incr device_idx 
      } else { 
       # close the plink connection. I'm guessing here 
       send \003  ;# Ctrl-C 
       expect eof 
       # re-do with current device 
      } 
      continue 
     } 

     "#" 
    } 

    # ... whatever you do when you're logged in 

    # and logout. something like 
    send "quit\r" 
    expect eof 

    # and on to the next device 
    set auth_idx 0 
    incr device_idx 
} 
+0

感謝您的職位格倫。好東西。!這個「incr auth_inx」功能看起來是我需要的重要組成部分。如果第一次登錄失敗,我們可以產生一個新的會話,然後應用第二組信用?我問,因爲目標設備不會回到登錄提示的開始處,它會繼續詢問最初輸入的用戶名的密碼,並且有兩個不同的用戶名。 即 「登錄爲:somepass SomeUser的@ somedevice的密碼: 拒絕訪問 SomeUser的@ somedevice的密碼: 拒絕訪問 SomeUser的@ somedevice的密碼: – helloworldhello

+0

@glenjackman您的解決方案的偉大工程!但是,現在又出現了另一個變量,那就是「連接超時」響應(當目標主機無法訪問時)我可以添加一個「else if」或其他東西來解決這個問題嗎? – helloworldhello

+0

看看我如何檢查「商店鑰匙」?在expect命令中添加另一個'pattern {condition}'對 –