expect簡介
expect是一款自動化的腳本解釋型的工具。
expect基於tcl腳本,expect腳本的運行需要tcl的支持。
expect對一些需要交互輸入的命令很有幫助,比如ssh ftp scp telnet。
遠程登錄linux服務器的時候,ssh命令需要手工輸入密碼,當登錄多台機器的時候就會非常繁瑣。
expect就可以根據設定的規則,自動幫我們輸入密碼,大大節省了時間。
expect安裝
一般機器不會自帶expect,需要手動安裝。
系統為RHEL/CentOS:
yum install expect
系統為Debian/Ubuntu:
apt-get install expect
expect基礎知識
expect腳本
腳本開頭
expect腳本一般以#!/usr/bin/expect -f開頭,類似bash腳本。
常用后綴
expect腳本常常以.exp或者.ex結束。
expect主要命令
- spawn 新建一個進程,這個進程的交互由expect控制
- expect 等待接受進程返回的字符串,直到超時時間,根據規則決定下一步操作
- send 發送字符串給expect控制的進程
- set 設定變量為某個值
- exp_continue 重新執行expect命令分支
- [lindex $argv 0] 獲取expect腳本的第1個參數
- [lindex $argv 1] 獲取expect腳本的第2個參數
- set timeout -1 設置超時方式為永遠等待
- set timeout 30 設置超時時間為30秒
- interact 將腳本的控制權交給用戶,用戶可繼續輸入命令
- expect eof 等待spawn進程結束后退出信號eof
expect命令分支
expect命令采用了tcl的模式-動作語法,此語法有以下幾種模式:
單一分支語法
set password 123456
expect "*assword:" { send "$password\r" }
當輸出中匹配*assword:時,輸出password變量的數值和回車。
多分支模式語法
set password 123456
expect {
"(yes/no)?" { send "yes\r"; exp_continue }
"*assword:" { send "$password\r" }
}
當輸出中包含(yes/no)?時,輸出yes和回車,同時重新執行此多分支語句。
當輸出中匹配*assword:時,輸出password變量的數值和回車。
expect詳細講解
ssh遠程登錄expect腳本
下面是一個自動登錄系統hostname1和hostname2執行uname -a后斷開連接的腳本。
先建立login.exp
touch login.exp
chmod +x login.exp
vim login.exp
內容如下:
#!/usr/bin/expect -f
set timeout -1 //永遠等待,不會超時
spawn ssh root@hostname1 //spawn 后面跟命令名稱和參數
//如果匹配到*assword,那么發送密碼,並進入下面的expect語句(uname -a語句)。
//如果匹配到yes/no,那么發送yes,並重新執行這個expect語句。
expect {
"*assword" {send "123456\r";}
"yes/no" {send "yes\r";exp_continue}
}
//匹配到*]#,那么運行uname -a命令
expect "*]#" {send "uname -a\r"}
send "exit\r" //退出遠程登錄
expect eof //結束spawn
//開始下一個命令
spawn ssh root@hostname2
expect {
"*assword" {send "123456\r";}
"yes/no" {send "yes\r";exp_continue}
}
expect "*]#" {send "uname -a\r"}
send "exit\r" //退出遠程登錄
expect eof //結束spawn
exit //退出expect腳本
ssh遠程登錄shell腳本(嵌套expect)
shell中使用expect -c "expect腳本內容"來完成嵌套。
注意:
expect腳本里面的"都需要在前面加上轉義符號\。
每個expect語句后面加上分號";"。
vim expect_in_shell.sh
#!/usr/bin/bash
HOSTS="hostname1 hostname2"
for host in $HOSTS
do
expect -c "
set timeout 5;
spawn ssh root@${host};
expect {
\"*assword\" { send \"123456\r\" }
\"yes/no\" { send \"yes\r\"; exp_continue }
} ;
expect \"*]#\" {send \"uname -a\r\" } ;
send \"exit\r\" //退出遠程登錄
expect eof
"
done
帶參數的expect腳本ssh登錄
vim login_arg.exp
#!/usr/bin/expect -f
set ip [lindex $argv 0] //第一個參數賦值給變量ip
set password [lindex $argv 1] //第二個參數復制給變量password
set timeout -1
spawn ssh root@$ip
expect {
"password" {send "$password\r";}
"yes/no" {send "yes\r";exp_continue}
}
interact //停留在遠程shell
帶參數運行login_arg.exp
chmod +x login_arg.exp
./login_arg.exp 127.0.0.1 123456