使用Expect編寫交互式腳本更改遠(yuǎn)程服務(wù)器密碼

我們經(jīng)常會遇到一些需要與服務(wù)器程序打交道的場景,比如涛舍,從登陸某個(gè)服務(wù)器澄惊,然后進(jìn)行某項(xiàng)工作。這很平常富雅,但是如果把這個(gè)工作自動化進(jìn)行掸驱,你就需要一個(gè)程序能自動做你要告訴機(jī)器的事情,這樣吹榴,我們的expect就能大顯身手了亭敢。

首先,expect是一個(gè)簡單的工具語言图筹,如要工作就是進(jìn)行自動化的人機(jī)交互帅刀。它的作者對Expect的定義:是一個(gè)實(shí)現(xiàn)自動交互功能的軟件套件(a software suite for automating interactive tools),使用expect,它能幫助我們在合適的情景下進(jìn)行合適的交互远剩。

#! /usr/bin/expect -f
set timeout 20
spawn ssh root@$IP
expect {
    "*RSA key*" {send "yes\r"}
    "*password:" {send "$ORI_PASSWD\r"}
}
expect "*#*" 
send "ls\r"
send "passwd\r"
expect {
     "*password:" {send "$NEW_PASSWD\r"}
     "新的 密碼:" {send "$NEW_PASSWD\r"}
}
send "exit\r"
exit
EOF

現(xiàn)在來解釋一下:
expect 的核心功能扣溺,對于設(shè)定好的特定匹配形式,以相匹配的動作以應(yīng)對瓜晤。每一個(gè)expect后所跟的字符串(或者正則表達(dá)式)就是腳本所等待的匹配模式锥余,每一個(gè)send 所做的工作就是對于各種的模式串,實(shí)施相應(yīng)的動作痢掠。
第一行設(shè)定了腳本執(zhí)行的程序,-f選項(xiàng)指的是expect執(zhí)行一個(gè)文件
第二行驱犹,設(shè)定了本腳本所有的超時(shí)時(shí)間,單位是秒(s),如果超時(shí)足画,腳本將繼續(xù)向下進(jìn)行(比如在等待某個(gè)模式出現(xiàn)雄驹,超時(shí)以后,會進(jìn)行下一語句淹辞,這里的下一句是expcet匹配超時(shí)失敗医舆,但依然執(zhí)行的是下一行send,或許將send用{}括起來可以解決這個(gè)問題)。
第三行蔬将,expect使用spawn(繁衍)命令來啟動腳本和命令會話爷速,這里啟動的是ssh命令,這里的ssh命令將會以子進(jìn)程的方式產(chǎn)生霞怀。
下面就是交互的過程:ssh 登陸以后惫东,會給要求客戶寫入密碼,所以等待出現(xiàn)“password:”,出現(xiàn)password:以后毙石,需要寫入密碼凿蒜,注意這里需要送去回車或者換行符,否則遠(yuǎn)端主機(jī)不會收到ssh請求的胁黑。登陸上系統(tǒng)之后废封,會出現(xiàn)命令提示符:~$,即系統(tǒng)已經(jīng)登陸到了遠(yuǎn)端主機(jī)的shell丧蘸,然后送去要執(zhí)行的命令漂洋。完畢后推出遠(yuǎn)程機(jī)器(這個(gè)send "exit\r"前也可以有上一個(gè)命令的輸出,也可以沒有力喷,因?yàn)樯弦粋€(gè)命令執(zhí)行完畢后會順序執(zhí)行下一條)刽漂。 expect {}是多行期望,匹配到哪條執(zhí)行哪條弟孟。背景:有時(shí)執(zhí)行shell后預(yù)期結(jié)果是不固定的贝咙,有可能是詢問是yes/no,有可能是去輸入密碼拂募,所以可以用expect{}庭猩。花括號內(nèi)放多行語句陈症,從上至下匹配蔼水,匹配到哪個(gè)expect執(zhí)行哪句。
最后是等待標(biāo)示子進(jìn)程已結(jié)束的標(biāo)示符eof录肯,然后退出趴腋。(注:這個(gè)等待eof必須要有,如果沒有eof论咏,很可能在子進(jìn)程沒有結(jié)束前就退出优炬,造成問題。)
interact:退出expect返回終端厅贪,可以繼續(xù)輸入蠢护,否則將一直在expect不能退出到終端
上面腳本執(zhí)行效果:
[圖片]
模式例子:

expect {
    "A" { do a }
    "B" { do b }
    timeout { do timeout }
}

過程
某些代碼有時(shí)是需要重復(fù)操作的,比如手機(jī)在某些特定的情況下可能需要反復(fù)重啟等卦溢,此時(shí)我們可以將其寫在某一個(gè)過程中糊余,直接調(diào)用該過程,以減少和簡化代碼单寂。

proc restartPhone {x} { 
if {$x == 1} { 
spawn adb shell 
expect "~# " 
send "reboot\r" 
expect "*" 
} else { 

} 
} 

如上贬芥,在需求重啟手機(jī)時(shí),我們只要調(diào)用”restartPhone 1"便可以了宣决。
第一版批量修改機(jī)器登錄密碼腳本:

#! /bin/sh
master_ip=192.168.1.106
master_user=liuhao
master_passwd=toor
PWD=`pwd`
LOG_DIR=logd
filename=iptab

if [ ! -d $PWD/$LOG_DIR ];then
    mkdir $PWD/$LOG_DIR
else
    rm -rf $PWD/$LOG_DIR/*
fi
IPLOG_FILE=$PWD/$LOG_DIR/logIP
echo "" > $IPLOG_FILE
while read -r line
do
    #echo $line
    ##下面一行代碼展示了如何將awk中的變量導(dǎo)出到shell(腳本)變量中使用的技巧
    eval $(echo $line | awk '{printf("IP=%s;ORI_PASSWD=%s;NEW_PASSWD=%s",$1,$2,$3);}')
    #echo $IP $ORI_PASSWD $NEW_PASSWD
    echo "will login $IP" >> $IPLOG_FILE
    expect <<-EOF
        set timeout 40
        spawn ssh root@$IP
        expect {
            "*RSA key*" {send "yes\r";exp_continue}
            "*password:" {send "$ORI_PASSWD\r"}
            timeout {send "touch $PWD/$LOG_DIR/$IP.loginfail\r";exit}
        }
        send "ifconfig\r"
        expect {
            "*$IP*" {send "ls\r"}
            timeout {send "touch $PWD/$LOG_DIR/$IP.loginfail\r";exit}
        }
        send "passwd\r"
        expect {
            "*password:" {send "$NEW_PASSWD\r"}
            "*新的*" {send "$NEW_PASSWD\r"}
            timeout {send "exit\r";exit}
        }
        expect {
            "*password:" {send "$NEW_PASSWD\r"}
            "*重新*" {send "$NEW_PASSWD\r"}
            timeout {send "exit\r";exit}
        }
        expect {
            "*成功*" {send "touch $IP\r"}
            "*updated successfully" {send "touch $IP\r"}
            timeout {send "exit\r";exit}
        }
        send "ls\r"
        expect {
            "$IP" {
                send "scp $IP $master_user@$master_ip:$PWD/$LOG_DIR/\r"
                expect {
                    "*RSA key*" {send "yes\r";exp_continue}
                    "*password:" {send "$master_passwd\r"}
                }
            }
        }
        send "exit\r"
        exit
    EOF
    echo "logouted from $IP" >> $IPLOG_FILE
done < $filename

第二版將日志信息直接寫入本地文件

#! /bin/sh

PWD=`pwd`
LOG_DIR=logd
filename=iptab

if [ ! -d $PWD/$LOG_DIR ];then
    mkdir $PWD/$LOG_DIR
else
    rm -rf $PWD/$LOG_DIR/*
fi

IPLOG_FILE=$PWD/$LOG_DIR/logIP
LOG_CHANGE=$PWD/$LOG_DIR/logChange
echo "" > $IPLOG_FILE
echo "" > $LOG_CHANGE

while read -r line
do
    #echo $line
    ##下面一行代碼展示了如何將awk中的變量導(dǎo)出到shell(腳本)變量中使用的技巧
    eval $(echo $line | awk '{printf("IP=%s;ORI_PASSWD=%s;NEW_PASSWD=%s",$1,$2,$3);}')
    #echo $IP $ORI_PASSWD $NEW_PASSWD
    echo "will login $IP" >> $IPLOG_FILE
    expect <<-EOF
        set timeout 40
        #這里打開文件要用append追加模式蘸劈,而不可以用w寫模式,寫模式默認(rèn)先清除文件內(nèi)容
        set ofile [open "$LOG_CHANGE" a]
        log_user 1
        spawn ssh root@$IP
        expect {
            "*password:" {send "$ORI_PASSWD\r"}
            "*RSA key*" {send "yes\r";exp_continue}
            timeout {puts \$ofile "login $IP failed,login timeout";close \$ofile;exit}
        }
        expect {
            "Permission denied*" {puts \$ofile "login $IP failed,wrong passwd";close \$ofile;exit}
            "*#*" {send "ifconfig\r"}
            timeout {puts \$ofile "login $IP failed";close \$ofile;exit}
        }
        
        expect {
            "*$IP*" {send "ls\r"}
            timeout {puts \$ofile "login $IP failed";close \$ofile;exit}
        }
        puts \$ofile "login $IP OK"
        send "passwd\r"
        expect {
            "*password:" {send "$NEW_PASSWD\r"}
            "*新的*" {send "$NEW_PASSWD\r"}
            timeout {puts \$ofile "passwd $IP failed";close \$ofile;send "exit\r";exit}
        }
        expect {
            "*password:" {send "$NEW_PASSWD\r"}
            "*重新*" {send "$NEW_PASSWD\r"}
            timeout {puts \$ofile "passwd $IP failed";close \$ofile;send "exit\r";exit}
        }
        expect {
            "*成功*" {puts \$ofile "passwd $IP successfully"}
            "*updated successfully" {puts \$ofile "passwd $IP successfully"}
            timeout {puts \$ofile "passwd $IP failed"}
        }
        close \$ofile
        send "exit\r"
        exit
    EOF
    echo "logouted from $IP" >> $IPLOG_FILE
done < $filename
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末尊沸,一起剝皮案震驚了整個(gè)濱河市威沫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌洼专,老刑警劉巖棒掠,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異屁商,居然都是意外死亡烟很,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門蜡镶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來雾袱,“玉大人,你說我怎么就攤上這事官还∏巯穑” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵望伦,是天一觀的道長林说。 經(jīng)常有香客問我,道長屯伞,這世上最難降的妖魔是什么述么? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮愕掏,結(jié)果婚禮上度秘,老公的妹妹穿的比我還像新娘。我一直安慰自己饵撑,他們只是感情好剑梳,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著滑潘,像睡著了一般垢乙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上语卤,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天追逮,我揣著相機(jī)與錄音酪刀,去河邊找鬼。 笑死钮孵,一個(gè)胖子當(dāng)著我的面吹牛骂倘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播巴席,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼历涝,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了漾唉?” 一聲冷哼從身側(cè)響起荧库,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赵刑,沒想到半個(gè)月后分衫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡般此,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年丐箩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恤煞。...
    茶點(diǎn)故事閱讀 40,503評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡屎勘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出居扒,到底是詐尸還是另有隱情概漱,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布喜喂,位于F島的核電站瓤摧,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏玉吁。R本人自食惡果不足惜照弥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望进副。 院中可真熱鬧这揣,春花似錦、人聲如沸影斑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽矫户。三九已至片迅,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間皆辽,已是汗流浹背柑蛇。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工芥挣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人耻台。 一個(gè)月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓空免,卻偏偏與公主長得像,于是被迫代替她去往敵國和親粘我。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 請不要轉(zhuǎn)載 背景介紹 Expect 程序主要用于人機(jī)對話的模擬痹换,就是那種系統(tǒng)提問征字,人來回答 yes/no ,或者賬...
    羽風(fēng)之歌閱讀 53,525評論 12 46
  • 前段時(shí)間寫了一篇Node.js 靜態(tài)資源打包上傳腳本的博客娇豫,今天又花了些時(shí)間使用 expect 編寫了一版匙姜。主要完...
    皺巴巴閱讀 664評論 2 0
  • .bat腳本基本命令語法 目錄 批處理的常見命令(未列舉的命令還比較多,請查閱幫助信息) 1冯痢、REM 和 :: 2...
    慶慶慶慶慶閱讀 8,109評論 1 19
  • 昨晚8點(diǎn)開始睡到今天早上9點(diǎn)氮昧,起來吃完早餐之后去照相,聽到照相的那個(gè)女的說很害怕很害怕浦楣,我當(dāng)時(shí)給分享說心定就...
    心靈自由路閱讀 148評論 0 0
  • 現(xiàn)在這個(gè)時(shí)間了袖肥,我還奮斗在一線,有人能求出我的心理陰影面積嗎振劳?(本人好絕望)
    盛望啊閱讀 248評論 4 10