2016-01-23 120 views
1

我寫了一個期望腳本的工作原理如下:而在循環問題expect腳本

  1. SSH到server1
  2. 在Server1 SSH到另一臺服務器服務器2
  3. 從服務器2到server(服務器),然後須藤成一個用戶並運行這些命令。

在腳本中,我從兩個名爲hostnames.out和commands.out的文件中讀取要執行的主機名和命令。我使用了一個while循環遍歷hostnames.out中的每個條目並從commands.out文件運行命令。

我在hostnames.out中使用單個條目測試了我的腳本,但它工作正常,但是當我添加多行時,它並未從第二行開始在主機名上運行命令。

的commands.out文件的格式是(每行一個命令):

 
ls -lrt 
hostname 
whoami 

的hostnames.out文件的格式是:

 
server1 user password server2 user password server3 user password 

我已附加的腳本參考。請讓我知道問題出在哪裏。

#!/usr/bin/expect 
##################################################### 
# script to automate manual works - remote 2  # 
# Gopinath           # 
##################################################### 
#Variable declaration: 

#Setting variable "prompt" for multiple prompts: 
set prompt {[]$#%]\s*$} 

#Reading commands list from file: 

set fp1 [open "commands_list_2.out" "r"] 
set file_data [read $fp1] 
close $fp1 


# read the hosts file one line at a time 
# There should be no new line at the end of the hostnames.out file 

    set fp [open "hostnames_2.out" "r"] 

    while { [gets $fp data] >= 0 } { 

      set ssh1 [lindex $data 0] 
      set ssh1_usr [lindex $data 1] 
      set ssh1_pwd [lindex $data 2] 
     set ods [lindex $data 3] 
     set ods_usr [lindex $data 4] 
      set ods_pwd [lindex $data 5] 
     set serv1 [lindex $data 6] 
     set serv1_usr [lindex $data 7] 
     set serv1_pwd [lindex $data 8] 

      puts $ssh1 
     puts $ssh1_usr 
      puts $ssh1_pwd 
     puts $ods 
     puts $ods_usr 
     puts $ods_pwd 
     puts $serv1 
     puts $serv1_usr 
      puts $serv1_pwd 

    spawn -noecho ssh [email protected]$ssh1 
    expect { 

     "*password:" { send "$ssh1_pwd\r"} 
     "*route*" { puts "login failed"; exit 1 } 
     "timed out" { puts "login failed timed out"; exit 1 } 
     } 

     expect { 
       -re $prompt { send "whoami\r"} 
      }    


        expect -re $prompt { 

          send "ssh [email protected]$ods\r" }   
        expect { 
        "password:" { send "$ods_pwd\r" } 
         } 
       } 


      expect { 
     -re $prompt { send "whoami\r"} 
      } 


        expect -re $prompt { 

          send "ssh [email protected]$serv1\r" } 
        expect { 
        "password:" { send "$serv1_pwd\r" } 
         } 

        expect -re $prompt 


     foreach a [list $file_data] { 
     send "$a" 
     expect -re prompt 
     } 
      expect -re prompt { 
       send "exit\r" 
       } 
    expect eof 
    close $fp 
` 

+0

您是否收到任何錯誤訊息? – Dinesh

+0

不,我沒有得到任何錯誤信息,當我添加第二行到hostnames.out文件。 – smgopinath

回答

1

到目前爲止,我所看到的,主要的問題是,你有子進程的這個複雜鏈條上的一個沒有被清理妥善不同的主機。這是由你的代碼難以閱讀的不一致的縮進複合而成的。

的關鍵是要在Server1和Server2你的SSH會話只是 ssh來在鏈中的下一個服務器,和server(服務器)上的SSH會話只是做了須藤。最簡單的解決方法是使用exec ssh而不是sshexec sudo而不是sudo。然後,在最內層執行exit將導致所有這些中間程序也終止,並且您的expect eof將觸發。

spawn -noecho ssh [email protected]$ssh1 
expect { 
    "*route*" { puts "login failed"; exit 1 } 
    "timed out" { puts "login failed timed out"; exit 1 } 
    "*password:" { send "$ssh1_pwd\r"; exp_continue } 
    -re $prompt { send "whoami\r" } 
} 
expect -re $prompt { 
    send "exec ssh [email protected]$ods\r" 
} 
expect { 
    "password:" { send "$ods_pwd\r"; exp_continue } 
    -re $prompt { send "whoami\r" } 
} 
expect -re $prompt { 
    send "exec ssh [email protected]$serv1\r" 
} 
expect { 
    "password:" { send "$serv1_pwd\r"; exp_continue } 
    -re $prompt { send "whoami\r" } 
} 

# You seem to be missing the sudo here? 

foreach a [split $file_data "\n"] { 
    expect -re $prompt 
    send "$a" 
} 

expect -re $prompt 
send "exit\r" 
expect eof 
close;   ### TERMINATE THE SPAWN. IMPORTANT! 

您也有您正在使用[list $file_data]時,你應該有[split $file_data "\n"]打破它由線的問題。


上面的代碼需要循環遍歷每組證書。這部分是最容易被寫成這樣的事情(因爲你真的不會有足夠的數據線需要流處理):

set fp [open "hostnames_2.out" "r"] 
set hostnamedata [split [read $fp] "\n"] 
close $fp 

foreach line $hostnamedata { 
    lassign $line ssh1 ssh1_usr ssh1_pwd ods ods_usr ods_pwd serv1 serv1_usr serv1_pwd 

    # The code from above goes here 
} 

分別建議考慮設置在所有中間服務器上使用SSH公鑰,並使用ssh的-A選項。這可以大大簡化認證/授權部分而不會影響安全性。

+0

也注意到你可以傳遞一個命令來執行到ssh,比如'ssh user1 @ serv1 ssh user2 @ serv2 sudo yourcommand'。現在你只需要處理密碼的東西。 –