expect - 自動(dòng)交互腳本
目錄
expect參數(shù)
啟用選項(xiàng)
-
-c
:執(zhí)行腳本前先執(zhí)行的命令似谁,可多次使用弊琴。 -
-d
:debug模式渠退,可以在運(yùn)行時(shí)輸出一些診斷信息盈魁,與在腳本開始處使用exp_internal 1
相似乡范。 -
-D
:啟用交換調(diào)式器,可設(shè)一整數(shù)參數(shù)裁眯。 -
-f
:從文件讀取命令偎捎,僅用于使用#!時(shí)蠢终。如果文件名為"-",則從stdin讀取(使用"./-"從文件名為-的文件讀取)茴她。 -
-i
:交互式輸入命令寻拂,使用"exit"或"EOF"退出輸入狀態(tài)。 -
--
:標(biāo)示選項(xiàng)結(jié)束(如果你需要傳遞與expect選項(xiàng)相似的參數(shù)給腳本時(shí))丈牢,可放到#!
行:#!/usr/bin/expect --
祭钉。 -
-v
:顯示expect版本信息。
常用命令
# 命令行參數(shù)
# $argv己沛,參數(shù)數(shù)組慌核,使用[lindex $argv n]獲取,$argv 0為腳本名字
# $argc申尼,參數(shù)個(gè)數(shù)
set
username [lindex $argv 1]
# 獲取第1個(gè)參數(shù)
set
passwd
[lindex $argv 2]
# 獲取第2個(gè)參數(shù)
set
timeout 30
# 設(shè)置超時(shí)
# spawn是expect內(nèi)部命令垮卓,開啟ssh連接
spawn
ssh
-l username 192.168.1.1
# 判斷上次輸出結(jié)果里是否包含“password:”的字符串,如果有則立即返回师幕,否則就等待一段時(shí)間(timeout)后返回
expect
"password:"
# 發(fā)送內(nèi)容ispass(密碼粟按、命令等)
send
"ispass\r"
# 發(fā)送內(nèi)容給用戶
send_user
"$argv0 [lrange $argv 0 2]\n"
send_user
"It's OK\r"
# 執(zhí)行完成后保持交互狀態(tài),控制權(quán)交給控制臺(tái)(手工操作)霹粥。否則會(huì)完成后會(huì)退出灭将。
interact
|
命令介紹
- close:關(guān)閉當(dāng)前進(jìn)程的連接。
- debug:控制調(diào)試器蒙挑。
- disconnect:斷開進(jìn)程連接(進(jìn)程仍在后臺(tái)運(yùn)行)宗侦。
- 定時(shí)讀取密碼、執(zhí)行priv_prog
`send_user` `"password?\ "`
`expect_user -re` `"(.*)\n"`
`for` `{} 1 {} {`
`if` `{[fork]!=0} {``sleep` `3600;``continue``}`
`disconnect`
`spawn priv_prog`
`expect Password:`
`send` `"$expect_out(1,string)\r"`
`. . .`
`exit`
`}`
|
- exit:退出expect忆蚀。
- exp_continue [-continue_timer]:繼續(xù)執(zhí)行下面的匹配矾利。
- exp_internal [-f file] value:
expect范例
- 自動(dòng)telnet會(huì)話
`#!/usr/bin/expect -f`
`set` `ip [lindex $argv 0 ]` `# 接收第1個(gè)參數(shù),作為IP`
`set` `userid [lindex $argv 1 ]` `# 接收第2個(gè)參數(shù),作為userid`
`set` `mypassword [lindex $argv 2 ]` `# 接收第3個(gè)參數(shù),作為密碼`
`set` `mycommand [lindex $argv 3 ]` `# 接收第4個(gè)參數(shù),作為命令`
`set` `timeout 10` `# 設(shè)置超時(shí)時(shí)間`
`# 向遠(yuǎn)程服務(wù)器請(qǐng)求打開一個(gè)telnet會(huì)話馋袜,并等待服務(wù)器詢問用戶名`
`spawn telnet $ip`
`expect` `"username:"`
`# 輸入用戶名男旗,并等待服務(wù)器詢問密碼`
`send` `"$userid\r"`
`expect` `"password:"`
`# 輸入密碼,并等待鍵入需要運(yùn)行的命令`
`send` `"$mypassword\r"`
`expect` `"%"`
`# 輸入預(yù)先定好的密碼欣鳖,等待運(yùn)行結(jié)果`
`send` `"$mycommand\r"`
`expect` `"%"`
`# 將運(yùn)行結(jié)果存入到變量中察皇,顯示出來或者寫到磁盤中`
`set` `results $expect_out(buffer)`
`# 退出telnet會(huì)話,等待服務(wù)器的退出提示EOF`
`send` `"exit\r"`
`expect eof`
|
- 自動(dòng)建立FTP會(huì)話
`#!/usr/bin/expect -f`
`set` `ip [lindex $argv 0 ]` `# 接收第1個(gè)參數(shù),作為IP`
`set` `userid [lindex $argv 1 ]` `# 接收第2個(gè)參數(shù),作為Userid`
`set` `mypassword [lindex $argv 2 ]` `# 接收第3個(gè)參數(shù),作為密碼`
`set` `timeout 10` `# 設(shè)置超時(shí)時(shí)間`
`# 向遠(yuǎn)程服務(wù)器請(qǐng)求打開一個(gè)FTP會(huì)話,并等待服務(wù)器詢問用戶名`
`spawn` `ftp` `$ip`
`expect` `"username:"`
`# 輸入用戶名什荣,并等待服務(wù)器詢問密碼`
`send` `"$userid\r"`
`expect` `"password:"`
`# 輸入密碼矾缓,并等待FTP提示符的出現(xiàn)`
`send` `"$mypassword\r"`
`expect` `"ftp>"`
`# 切換到二進(jìn)制模式,并等待FTP提示符的出現(xiàn)`
`send` `"bin\r"`
`expect` `"ftp>"`
`# 關(guān)閉ftp的提示符`
`send` `"prompt\r"`
`expect` `"ftp>"`
`# 下載所有文件`
`send` `"mget *\r"`
`expect` `"ftp>"`
`# 退出此次ftp會(huì)話稻爬,并等待服務(wù)器的退出提示EOF`
`send` `"bye\r"`
`expect eof`
|
- 自動(dòng)登錄ssh執(zhí)行命令
`#!/usr/bin/expect`
`set` `IP [lindex $argv 0]`
`set` `USER [lindex $argv 1]`
`set` `PASSWD [lindex $argv 2]`
`set` `CMD [lindex $argv 3]`
`spawn` `ssh` `$USER@$IP $CMD`
`expect {`
`"(yes/no)?"` `{`
`send` `"yes\r"`
`expect` `"password:"`
`send` `"$PASSWD\r"`
`}`
`"password:"` `{send` `"$PASSWD\r"``}`
`"* to host"` `{``exit` `1}`
`}`
`expect eof`
|
- 自動(dòng)登錄ssh
`#!/usr/bin/expect -f `
`set` `ip [lindex $argv 0 ]` `# 接收第1個(gè)參數(shù),作為IP`
`set` `username [lindex $argv 1 ]` `# 接收第2個(gè)參數(shù),作為username`
`set` `mypassword [lindex $argv 2 ]` `# 接收第3個(gè)參數(shù),作為密碼`
`set` `timeout 10` `# 設(shè)置超時(shí)時(shí)間`
`spawn` `ssh` `$username@$ip` `# 發(fā)送ssh請(qǐng)求`
`expect {` `# 返回信息匹配`
`"*yes/no"` `{ send` `"yes\r"``; exp_continue}` `# 第一次ssh連接會(huì)提示yes/no,繼續(xù) `
`"*password:"` `{ send` `"$mypassword\r"` `}` `# 出現(xiàn)密碼提示,發(fā)送密碼 `
`}`
`interact` `# 交互模式,用戶會(huì)停留在遠(yuǎn)程服務(wù)器上面`
|
- 批量登錄ssh服務(wù)器執(zhí)行操作范例嗜闻,設(shè)定增量的for循環(huán)
`#!/usr/bin/expect`
`for` `{``set` `i 10} {$i <= 12} {incr i} {`
`set` `timeout 30`
`set` `ssh_user [lindex $argv 0]`
`spawn` `ssh` `-i .``ssh``/$ssh_user abc$i.com`
`expect_before` `"no)?"` `{`
`send` `"yes\r"` `}`
`sleep` `1`
`expect` `"password*"`
`send` `"hello\r"`
`expect` `"*#"`
`send` `"echo hello expect! > /tmp/expect.txt\r"`
`expect` `"*#"`
`send` `"echo\r"`
`}`
`exit`
|
- 批量登錄ssh并執(zhí)行命令,foreach語法
`#!/usr/bin/expect`
`if` `{$argc!=2} {`
`send_user` `"usage: ./expect ssh_user password\n"`
`exit`
`}`
`foreach i {11 12} {`
`set` `timeout 30`
`set` `ssh_user [lindex $argv 0]`
`set` `password [lindex $argv 1]`
`spawn` `ssh` `-i .``ssh``/$ssh_user root@xxx.yy.com`
`expect_before` `"no)?"` `{`
`send` `"yes\r"` `}`
`sleep` `1`
`expect` `"Enter passphrase for key*"`
`send` `"password\r"`
`expect` `"*#"`
`send` `"echo hello expect! > /tmp/expect.txt\r"`
`expect` `"*#"`
`send` `"echo\r"`
`}`
`exit`
|
- 另一自動(dòng)ssh范例桅锄,從命令行獲取服務(wù)器IP琉雳,foreach語法,expect嵌套
`#!/usr/bin/expect`
`# 使用方法: script_name ip1 ip2 ip3 ...`
`set` `timeout 20`
`if` `{$argc < 1} {`
`puts` `"Usage: script IPs"`
`exit` `1`
`}`
`# 替換你自己的用戶名`
`set` `user` `"username"`
`#替換你自己的登錄密碼`
`set` `password` `"yourpassword"`
`foreach IP $argv {`
`spawn` `ssh` `$user@$IP`
`expect \`
`"(yes/no)?"` `{`
`send` `"yes\r"`
`expect` `"password:?"` `{`
`send` `"$password\r"`
`}`
`}` `"password:?"` `{`
`send` `"$password\r"`
`}`
`expect` `"\$?"`
`# 替換你要執(zhí)行的命令`
`send` `"last\r"`
`expect` `"\$?"`
`sleep` `10`
`send` `"exit\r"`
`expect eof`
`}`
|
- 批量ssh執(zhí)行命令友瘤,用shell調(diào)用tclsh方式翠肘、多進(jìn)程同時(shí)執(zhí)行
- tclsh - Simple shell containing Tcl interpreter
`#!/bin/sh`
`# -*- tcl -*- \`
`exec` `tclsh $0` `"$@"`
`package require Expect`
`set` `username [lindex $argv 0]`
`set` `password [lindex $argv 1]`
`set` `argv [lrange $argv 2 end]`
`set` `prompt` `"(%|#|\\$) $"`
`foreach ip $argv {`
`spawn` `ssh` `-t $username@$ip sh`
`lappend ids $spawn_id`
`}`
`expect_before -i ids eof {`
`set` `index [lsearch $ids $expect_out(spawn_id)]`
`set` `ids [lreplace $ids $index $index]`
`if` `[llength $ids] exp_continue`
`}`
`expect -i ids` `"(yes/no)\\?"` `{`
`send -i $expect_out(spawn_id)` `yes``\r`
`exp_continue`
`} -i ids` `"Enter passphrase for key"` `{`
`send -i $expect_out(spawn_id) \r`
`exp_continue`
`} -i ids` `"assword:"` `{`
`send -i $expect_out(spawn_id) $password\r`
`exp_continue`
`} -i ids -re $prompt {`
`set` `spawn_id $expect_out(spawn_id)`
`send` `"echo hello; exit\r"`
`exp_continue`
`} timeout {`
`exit` `1`
`}`
|
-
ssh登錄過程常規(guī)提示文字
<pre style="margin: 0.5em 0px 1em 1em; white-space: pre-wrap; word-wrap: break-word; padding: 0.4em 0.8em; background: rgba(255, 30, 120, 0.117647); border-width: 1px; border-style: solid; border-color: rgb(102, 17, 68) rgb(102, 17, 68) rgb(102, 17, 68) rgb(204, 34, 102); border-image: initial; position: relative; z-index: 2; font-family: "Lucida Console", "Courier New", Courier, monospace; transition: all 0.45s linear;">The authenticity of host '192.168.17.35 (192.168.17.35)' can't be established.
RSA key fingerprint is 25:e8:4c:89:a3:b2:06:ee:de:66:c7:7e:1b:fa:1c:c5.
Are you sure you want to continue connecting (yes/no)?Warning: Permanently added '192.168.17.35' (RSA) to the list of known hosts.
Enter passphrase for key '/data/key/my_dsa':Last login: Sun Jan 26 13:39:37 2014 from 192.168.11.143
[root@master003 ~]#root@192.168.16.90's password:
Last login: Thu Jan 23 17:50:43 2014 from 192.168.11.102
[root@lvsmaster ~]#
</pre> ssh自動(dòng)登錄expect腳本:ssh.expect
`#!/usr/bin/expect -f`
`# Auther:YuanXing`
`# Update:2014-02-08`
`if` `{$argc < 4} {`
`send_user` `"Usage:\n $argv0 IPaddr User Passwd Port Passphrase\n"`
`puts stderr` `"argv error!\n"`
`sleep` `1`
`exit` `1`
`}`
`set` `ip [lindex $argv 0 ]`
`set` `user [lindex $argv 1 ]`
`set` `passwd` `[lindex $argv 2 ]`
`set` `port [lindex $argv 3 ]`
`set` `passphrase [lindex $argv 4 ]`
`set` `timeout 6`
`if` `{$port ==` `""``} {`
`set` `port 22`
`}`
`#send_user "IP:$ip,User:$user,Passwd:$passwd,Port:$port,Passphrase:$passphrase"`
`spawn` `ssh` `-p $port $user@$ip`
`expect_before` `"(yes/no)\\?"` `{`
`send` `"yes\r"``}`
`expect \`
`"Enter passphrase for key*"` `{`
`send` `"$passphrase\r"`
`exp_continue`
`}` `" password:?"` `{`
`send` `"$passwd\r"`
`exp_continue`
`}` `"*\[#\\\$]"` `{`
`interact`
`}` `"* to host"` `{`
`send_user` `"Connect faild!"`
`exit` `2`
`} timeout {`
`send_user` `"Connect timeout!"`
`exit` `2`
`} eof {`
`send_user` `"Lost connect!"`
`exit`
`}`
|
- Mikrotik backup script using ssh and expect
`#!/bin/bash`
`# BY: Pejman Moghadam`
`# TAG: mikrotik, ssh, expect, lftp`
`# DATE: 2012-05-27 14:42:14`
`BACKUP_DIR=``"/var/backups"`
`HOSTNAME=``"192.168.88.1"`
`PORT=``"22"`
`USER=``"admin"`
`PASS=``"123456"`
`TMP=$(mktemp)`
`TODAY=$(``date` `+%F)`
`FILENAME=``"$HOSTNAME-$TODAY"`
`PATH=``"/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin"`
`# create expect script`
`cat` `> $TMP << EOF`
`#exp_internal 1 # Uncomment for debug`
`set` `timeout -1`
`spawn` `ssh` `-p$PORT $USER@$HOSTNAME`
`match_max 100000`
`expect -exact` `"password:"`
`send --` `"$PASS\r"`
`sleep` `1`
`expect` `" > "`
`send --` `"/export file=$FILENAME\r"`
`expect` `" > "`
`send --` `"/system backup save name=$FILENAME\r"`
`expect` `" > "`
`send --` `"quit\r"`
`expect eof`
`EOF`
`# run expect script`
`#cat $TMP # Uncomment for debug`
`expect -f $TMP`
`# remove expect script`
`rm` `$TMP`
`# download and remove backup files`
`# "xfer:clobber on" means overwrite existing files`
`cd` `${BACKUP_DIR}`
`echo` `"`
`set` `xfer:clobber on`
`get ${FILENAME}.rsc`
`rm` `${FILENAME}.rsc`
`get ${FILENAME}.backup`
`rm` `${FILENAME}.backup" |`
`lftp -u $USER,$PASS $HOSTNAME`
|