Expect交互

我們通過Shell可以實現簡單的控制流功能,如:循環、判斷等。但是對於需要交互的場合則必須通過人工來干預,有時候我們可能會需要實現和交互程序如telnet服務器等進行交互的功能。而expect就使用來實現這種功能的工具。expect是一個免費的編程工具語言,用來實現自動和交互式任務進行通信,而無需人的干預(如:藉助Expect處理交互的命令,可以將交互過程:ssh登錄,ftp登錄等寫在一個腳本上,使之自動化完成。尤其適用於需要對多臺服務器執行相同操作的環境中,可以大大提高系統管理人員的工作效率)。expect需要Tcl編程語言的支持,要在系統上運行expect必須首先安裝Tcl。

Expect是Unix系統中用來進行自動化控制和測試的軟件工具,由Don Libes製作,作爲Tcl腳本語言的一個擴展,應用在交互式軟件如telnet,ftp,Passwd,fsck,rlogin,tip,ssh等等。該工具利用Unix僞終端包裝其子進程,允許任意程序通過終端接入進行自動化控制;
expect 是基於tcl 演變而來的,所以很多語法和tcl 類似

基本的語法如下 所示:

首行加上/usr/bin/expect
spawn: 後面加上需要執行的shell 命令,比如說spawn sudo touch testfile;也即啓動新的進程
expect: 只有spawn 執行的命令結果纔會被expect 捕捉到,因爲spawn 會啓
動一個進程,只有這個進程的相關信息纔會被捕捉到,主要包括:標準輸入的提示信息,eof 和timeout。也即從新進程接收字符串
send 和send_user:send 會將expect 腳本中需要的信息發送給spawn 啓動
的那個進程,而send_user 只是回顯用戶發出的信息,類似於shell 中的echo 而
已。用於向進程發送字符串
interact:允許用戶交互
#yum -y install tcl
#yum -y install expect

Expect用法:

Expect中最關鍵的四個命令是send,expect,spawn,interact。
send:用於向進程發送字符串
expect:從進程接收字符串
spawn:啓動新的進程
interact:允許用戶交互
#!/usr/bin/expect
這一行告訴操作系統腳本里的代碼使用那一個shell來執行。這裏的expect其實和linux下的bash、windows下的cmd是一類東西。
注意:這一行需要在腳本的第一行。

set timeout 30
這是設置超時時間的,現在你只要記住他的計時單位是:秒 ,timeout -1 爲永不超時。

spawn ssh –l username 192.168.1.100
spawn是進入expect環境後纔可以執行的expect內部命令,如果沒有裝expect或者直接在默認的SHELL下執行是找不到spawn命令的。它主要的功能是給ssh運行進程加個殼,用來傳遞交互指令。

上文的所有demo都是和標準輸入輸出進行交互,但是我們跟希望他可以和某一個進程進行交互。spawn命令就是用來啓動新的進程的。spawn後的send和expect命令都是和spawn打開的進程進行交互的。結合上文的send和expect命令我們可以看一下更復雜的程序段了。
set timeout -1
spawn ftp ftp.test.com //打開新的進程,該進程用戶連接遠程ftp服務器
expect “Name” //進程返回Name時
send “user\r” //向進程輸入user\r
expect “Password:” //進程返回Password:時
send “123456\r” //向進程輸入123456\r
expect "ftp> " //進程返回ftp>時
send “binary\r” //向進程輸入binary\r
expect "ftp> " //進程返回ftp>時
send “get test.tar.gz\r” //向進程輸入get test.tar.gz\r

expect “password:”
這裏的expect也是expect的一個內部命令,expect的shell命令和內部命令是一樣的,但不是一個功能,這個命令的意思是判斷上次輸出結果裏是否包含“password:”的字符串,如果有則立即返回,否則就等待一段時間後返回,這裏等待時長就是前面設置的30秒

send “ispass\r”
這裏就是執行交互動作,與手效工輸入密碼的動作等。命令字符串結尾別忘記加上“\r”,如果出現異常等待的狀態可以覈查一下。Send命令接收一個字符串參數,並將改參數發送到進程。

Interact
執行完成後保持交互狀態,把控制權交給控制檯,這個時候就可以手工操作了。如果沒有這一句登錄完成後會退出,而不是留在遠程終端上。如果你只是登錄過去執行 .
spawn ftp localhost
expect “Name”
send “user\r”
expect “Password:”
send “123456\r”
interact
注意:expect腳本必須以interact或expect eof結束,執行自動化任務通常expect eof就夠了。

實例解析:

先安裝yum -y install expect yum -y install tcl
新建用戶並修改密碼useradd dd passwd dd
#vi ssh.exp
#!/usr/bin/expect
spawn ssh [email protected]
expect “password:"
send “123456\r”
expect "
#”
Interact
在這裏插入圖片描述

事例2(-c選項使用)

expect可以讓你使用“-c”選項,直接在命令行中執行它,如下所示:
#expect -c ‘expect “\n” {send “pressed enter\n”}’
pressed enter
如果你執行了上面的腳本,它會等待輸入換行符(\n)。按“enter”鍵以後,它會打印出“pressed enter”這個消息,然後退出。

事例3(-i選項使用)

使用“-i”選項,可以通過來自於標準輸入的讀命令來交互地執行expect腳本。
#expect -i arg1 arg2 arg3
expect1.1> set argv
arg1 arg2 arg3
expect1.2>
正常情況下,當你執行上面的expect命令的時候(沒有“-i”選項),它會把arg1當成腳本的文件名,所以“-i”選項可以讓腳本把多個參數當成一個連續的列表。
當你執行帶有“-c”選項的expect腳本的時候,這個選項是十分有用的。因爲默認情況下,expect是交互地執行的。
-d選項:執行expect腳本時,輸出調試信息
-D選擇:用於啓動調試器,它只接受一個布爾值的參數,這個參數表示提示器必須馬上啓動,還只是初始化調試器,以後再使用它。

事例4:

#!/usr/bin/expect
set timeout 30
spawn ssh -l username 192.168.1.1
expect “password:”
send “ispass\r”
interact
[#!/usr/bin/expect]
這一行告訴操作系統腳本里的代碼使用那一個shell來執行。這裏的expect其實和linux下的bash、windows下的cmd是一類東西。
注意:這一行需要在腳本的第一行。
[set timeout 30]
基本上認識英文的都知道這是設置超時時間的,現在你只要記住他的計時單位是:秒
[spawn ssh -l username 192.168.1.1]
spawn是進入expect環境後纔可以執行的expect內部命令,如果沒有裝expect或者直接在默認的SHELL下執行是找不到spawn命令的。所以不要用 “which spawn“之類的命令去找spawn命令。好比windows裏的dir就是一個內部命令,這個命令由shell自帶,你無法找到一個dir.com 或 dir.exe 的可執行文件。
它主要的功能是給ssh運行進程加個殼,用來傳遞交互指令。
[expect “password:”]
這裏的expect也是expect的一個內部命令,expect的shell命令和內部命令是一樣的,但不是一個功能,習慣就好了。這個命令的意思是判斷上次輸出結果裏是否包含“password:”的字符串,如果有則立即返回,否則就等待一段時間後返回,這裏等待時長就是前面設置的30秒
[send “ispass\r”]
這裏就是執行交互動作,與手工輸入密碼的動作等效。
提示: 命令字符串結尾別忘記加上 “\r”,如果出現異常等待的狀態可以覈查一下。
[interact]
執行完成後保持交互狀態,把控制權交給控制檯,這個時候就可以手工操作了。如果沒有這一句登錄完成後會退出,而不是留在遠程終端上。如果你只是登錄過去執行一段命令就退出,可改爲[expect eof]

事例5:expect實現ssh無祕鑰登錄

Shell腳本如下send_key.sh:
#!/bin/bash
ssh-keygen -t dsa
for (( i = 1; i <= 100 ; i ++ ))
do
./scp_key_to_node.exp $i
done
expect腳本scp_key_to_node.exp:
#!/usr/bin/expect
set timeout 5
set hostno [lindex argv0]spawnscp /.ssh/iddsa.pubimpalaargv 0] spawn scp ~/.ssh/id_dsa.pub impalahostno:~/.ssh/pub_key
expect “password
send “111111\r”
spawn ssh impalaKaTeX parse error: Can't use function '\r' in math mode at position 96: … send "111111\̲r̲" spawn ssh…hostno “chmod 600 ~/.ssh/authorized_keys”
expect “password
send “111111\r”
expect eof
分析:
set可以設置超時,或者設置一個變量的值
spawn是執行一個命令
expect等待一個匹配的輸出流中的內容
send是匹配到之後向輸入流寫入的內容
[lindex $argv 0]表示腳本的第0個參數
expect eof表示讀取到文件結束符

事例5:

Ssh實現自動登錄,並停留在登錄服務器上:
#!/usr/bin/expect -f
set ip [lindex $argv 0 ] //接收第一個參數,並設置IP
set password [lindex argv1]//,settimeout10//spawnsshroot@argv 1 ] //接收第二個參數,並設置密碼 set timeout 10 //設置超時時間 spawn ssh root@ip //發送ssh請滶
expect { //返回信息匹配
“*yes/no” { send “yes\r”; exp_continue} //第一次ssh連接會提示yes/no,繼續
“*password:” { send “$password\r” } //出現密碼提示,發送密碼
}
interact //交互模式,用戶會停留在遠程服務器上面.
運行結果如下:
#./test.exp 192.168.152.128 admin
spawn ssh [email protected]
Last login: Fri Sep 7 10:47:43 2012 from 192.168.152.130

事例6:

遠程登錄到服務器,並執行命令,執行完之後退出
#vi expect3.exp
#!/usr/bin/expect -f
set ip 192.168.152.130
set password 2008.cn
set timeout 10
spawn ssh root@KaTeX parse error: Can't use function '\r' in math mode at position 36: …no" { send "yes\̲r̲"; exp_continue…password\r" }
}
expect “#*”
send “pwd\r”
send “exit\r”
expect eof
在這裏插入圖片描述

事例6:

使用expect調用passwd自動更改密碼。
#vi exp4.exp
#!/bin/bash
USER=mynameuser
PASS=oldpassword
NPASS=newpassword
expect << EOF
spawn passwd
expect “Changing password for USER."send"{USER}." send "{PASS}\r”
expect “Enter new UNIX password:”
send “KaTeX parse error: Can't use function '\r' in math mode at position 8: {NPASS}\̲r̲" expect "Retyp…{NPASS}\r”
expect eof;
EOF

事例7:

遠程登錄ftp服務器,並下載文件:
#!/usr/bin/expect -f
set ip [lindex $argv 0 ]
set dir [lindex $argv 1 ]
set file [lindex $argv 2 ]
set timeout 10
spawn ftp $ip
expect “Name*”
send “zwh\r”
expect “Password:"
send “zwh\r”
expect "ftp>

send “lcd $dir\r”
expect {
“*file” { send_user “local $_dir No such file or directory”;send “quit\r” }
now” { send “get dir/dir/file dir/dir/file\r”}
}
expect {
“*Failed” { send_user “remote KaTeX parse error: Can't use function '\r' in math mode at position 30: …ile";send "quit\̲r̲" } "*OK" …file has been download\r”;send “quit\r”}
}
expect eof
#./exp5.exp 192.168.152.130 /var/www/ftp aaa.html

事例8:

根據IP地址和密碼不同連接到不同的機器:
#vi expect2.exp
#!/usr/bin/expect -f
set ip 192.168.152.130
set password 2008.cn
set timeout 10
spawn ssh root@KaTeX parse error: Can't use function '\r' in math mode at position 36: …no" { send "yes\̲r̲"; exp_continue…password\r" }
}
expect “*#”
interact
在這裏插入圖片描述

事例9:

#vi scp.sh
#!/usr/bin/expect
#本腳本用於自動遠程scp
set timeout 30
spawn scp /shell/scp.sh [email protected]:/usr/local/src/
expect “*password:”
send “2008.cn\r”
interact
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章