一、概述
我們通過Shell可以實現簡單的控制流功能,如:循環、判斷等。但是對於需要交互的場合則必須通過人工來干預,有時候我們可能會需要實現和交互程序如telnet服務器等進行交互的功能。而expect就使用來實現這種功能的工具。
安裝expect
yum -y install expect
四個命令
Expect中最關鍵的四個命令是send,expect,spawn,interact
send:用於向進程發送字符串
expect:從進程接收字符串
spawn:啟動新的進程,執行命令
interact:允許用戶交互
二、實例
在使用ansible時,需要進行ssh互信認證,及ansible操作端服務器需要免密登錄其他被控制端服務器。
如果服務器太多,一個一個輸入賬戶密碼就特別繁瑣了,此時可以通過expect腳本完成交互式操作。
1.先將需要免密登錄的遠程服務器IP寫入到hosts.txt文件,方便后續腳本調用
2.編寫腳本如下:
注:復制執行腳本時把中文注釋去掉,否則會有問題
#!/usr/bin/expect set timeout -1 #設置超時時間,永不超時 set username danny #設置SSH用戶名 set password danny123 #設置密碼 set hosts [open hosts.txt r] #以只讀的方式將hosts.txt中的值賦值給hosts參數 while { [gets $hosts IP] >= 0 } { spawn ssh-copy-id -i /root/.ssh/id_rsa.pub $username@$IP #spawn啟動腳本或命令的會話,以衍生子進程的方式來運行。 expect { "yes/no" {send "yes\r"; exp_continue} #交互式操作,輸入yes再回車 "password:" {send "${password}\r"} #輸入密碼,回車 } expect eof
#子進程運行完成之后,會得到標識子進程已經結束的eof字符,腳本結束(和spawn對應,當spawn發送指令到終端執行,在返回時被expect捕捉時,在起始會有一個eof標識字符) } close $hosts
執行(不要用sh auto_ssh.sh執行,這是expect腳本,會報格式錯誤)
./auto_ssh.sh
附兩個遠程上傳腳本示例:
腳本1、
#!/usr/bin/expect set username danny set password danny123 set port 21435 set host 192.168.1.10 set argv [lindex $argv 0] set timeout -1 spawn scp -P $port -o StrictHostKeyChecking=no -r $argv $username@$host:/home/danny expect "password:" send "$password\r" expect eof exit
執行:
./auto_scp.sh xxx.tar.gz
腳本2::
#!/bin/bash cd /root/product/ auto_smart_scp () { expect -c "set timeout -1; spawn scp $@; expect { *assword:* {send $pass\r; expect { *denied* {exit 2;} eof } } eof {exit 1;} } " return $? } pass='danny123' auto_smart_scp -P 21435 -o StrictHostKeyChecking=no -r $1 root@192.168.1.10:/root/temp
執行
sh auto_scp.sh xxx.tar.gz