shell脚本——expect命令
一、對expect的基本了解
?我們通過Shell可以實現簡單的控制流功能,如:循環、判斷等。但是對于需要交互的場合則必須通過人工來干預,有時候我們可能會需要實現和交互程序如telnet服務器等進行交互的功能。而expect就使用來實現這種功能的工具。
?????? expect是一個免費的編程工具語言,用來實現自動和交互式任務進行通信,而無需人的干預。expect是不斷發展的,隨著時間的流逝,其功能越來越強大,已經成為系統管理員的的一個強大助手。expect需要Tcl編程語言的支持,要在系統上運行expect必須首先安裝Tcl。
二、expect的安裝
expect是在Tcl基礎上創建起來的,所以在安裝expect前我們應該先安裝Tcl。
(一)Tcl 安裝
主頁:?http://www.tcl.tk
下載地址:?http://www.tcl.tk/software/tcltk/downloadnow84.tml
1.下載源碼包
?wget?http://nchc.dl.sourceforge.net/sourceforge/tcl/tcl8.4.11-src.tar.gz??
?
2.解壓縮源碼包?
tar?xfvz?tcl8.4.11-src.tar.gz??
?
3.安裝配置
注意:
1、安裝完畢以后,進入tcl源代碼的根目錄,把子目錄unix下面的tclUnixPort.h copy到子目錄generic中。
2、暫時不要刪除tcl源代碼,因為expect的安裝過程還需要用。
(二)expect 安裝 (需Tcl的庫)
主頁:?http://expect.nist.gov/
1.下載源碼包 wget?http://sourceforge.net/projects/expect/files/Expect/5.45/expect5.45.tar.gz/download
?
2.解壓縮源碼包
tar?xzvf?expect5.45.tar.gz??
?
3.安裝配置?
| shell腳本實現expect的安裝 |
| ######################################################## #(1)這部分實現expect的安裝 #(2)expect 需要 依賴tcl的庫 #(3)expect的位置 /use/expect/bin/expect; tcl位置 /usr/tcl/bin/tclsh8.4 #(4)注意:腳本每執行一次 就會安裝一次 ######################################################## function testInstal_pack() { echo -e "\033[32m-----------------------------------------------\033[0m" echo "This is going to install package $1!" if [ $1 == "tcl" ] then echo "tcl tcl" tar -xzf $TCLTAR_PATH -C $RUN_PATH cd $TCL_PATH/unix ./configure --prefix=/usr/tcl --enable-shared make && make install cp $TCL_PATH/unix/tclUnixPort.h $TCL_PATH/generic/ fi ? if [ $1 == "expect" ] then echo "aa" tar -xzf $EXPECTTAR_PATH -C $RUN_PATH cd $EXPECT_PATH ./configure --prefix=/usr/expect --with-tcl=/usr/tcl/lib --with-tclinclude=$TCL_PATH/generic make && make install ln -s /usr/tcl/bin/expect /usr/expect/bin/expect fi } #testInstal_pack openssl testInstal_pack tcl testInstal_pack expect |
三、expect的原理
| Linux expect 腳本的使用 |
| Expect的原理: ?????Expect腳本語言自動提交輸入到交互程序,它的工作原理是等待特定字符串,并發送或者響應相應的字符串。以下四個expect命令用于任何自動化的過程。 1、spawn:啟動命令 2、expect:等待來自進程的特定的字符串 3、send:發送字符串到進程 4、interact:允許用戶交互 |
3.1 首行加上/usr/bin/expect 但是在根據上述方式安裝后 應該為#!/usr/expect/bin/expect
3.2?spawn: 后面加上需要執行的shell命令,比如說spawn sudo touch testfile
3.3 expect:?只有spawn執行的命令結果才會被expect捕捉到,因為spawn會啟動一個進程,只有這個進程的相關信息才會被捕捉到,主要包括:標準輸入的提示信息,eof和timeout。
3.4 send和send_user:send會將expect腳本中需要的信息發送給spawn啟動的那個進程,而send_user只是回顯用戶發出的信息,類似于shell中的echo而已。
四、expect的使用實例
1、使用expect工具ssh登錄遠程服務器并執行命令操作
遠程交互從服務器A上ssh到服務器B上,然后執行服務器B上的命令
| #!/usr/expect/bin/expect -f ? set ipaddress [lindex $argv 0] set port [lindex $argv 1] set username [lindex $argv 2] set passwd [lindex $argv 3] set timeout 30 ? if {$argc != 4} { send "usage ./account.sh \$ipaddress \$port \$username \$passwd\n" exit } ? spawn ssh $ipaddress -p$port -l$username expect { "yes/no" { send "yes\r";exp_continue } "password:" { send "$passwd\r" } } expect -re "\](\$|#) " send "iptables -F\r" expect -re "\](\$|#) " send "exit\r" |
4.1 默認情況下 timeout是10秒,但是在ssh遠程登錄的時候建議改為30秒,否則會報錯“expect: spawn id exp4 not open,”
4.2 輸入的參數的數目,可以通過$argc得到;
4.3 參數存在$argv當中,比如取第一個參數就是[lindex $argv 0];并且如果需要計算的話必須用expr,如計算2-1,則必須用[expr 2-1];
4.4 下面我們來看一些expect的一些內部參數:
exp_continue [-continue_timer]
???????????? The command exp_continue allows expect itself to continue executing rather than returning as it? normally
???????????? would.? By? default? exp_continue? resets the timeout timer. The -continue_timer flag prevents timer from
???????????? being restarted.
exp_version [[-exit] version]
???????????? is useful for assuring that the script is compatible with the current version of Expect.
?????????????With? no? arguments, the current version of Expect is returned.? This version may then be encoded in your
???????????? script.? If you actually know that you are not using features of recent versions, you can specify an ear-
???????????? lier version.
執行結果如下:
| [root@slave1 workspace]# ./dotask.exp 192.168.1.93 usage ./account.sh $ipaddress $port $username $passwd [root@slave1 workspace]# ./dotask.exp 192.168.1.93 22 root asdfgh spawn ssh 192.168.1.93 -p22 -lroot root@192.168.1.93's password: Last login: Fri Jun 15 15:08:49 2018 from 192.168.1.177 [root@J01051386 ~]# iptables -F [root@J01051386 ~]# [root@slave1 workspace]# |
?
| 參考的鏈接:http://blog.sina.com.cn/s/blog_5432f2730100vcql.html |
| Expect說白了就是一個實現人機交互的命令工具,可以抓取和相應用戶輸入,也可以模擬用戶輸出。 ? 比如你有n臺服務器需要維護,要登錄到所有的服務器上執行某項操作(如添加用戶、修改一個用戶的密碼),如果按傳統方法,一個一個去登錄敲命令那就太麻煩了。可以通過expect寫成shell腳本來批量處理,具體如下: 如果系統里沒有expect請自行到官網下載安裝:http://expect.sourceforge.net/ 1、創建服務器列表配置文件: [root@localhost ~]# vi server_list.conf 192.168.0.10 22 root 123456 192.168.0.11 22 root 123456 192.168.0.12 60008 root 123456 ? 說明:配置文件有4列,以空格分割:服務器IP ssh端口號 用戶名 密碼 2、編寫expect腳本: [root@localhost ~]# vi dotask.exp #!/usr/bin/expect -f set ipaddress [lindex $argv 0] set port [lindex $argv 1] set username [lindex $argv 2] set passwd [lindex $argv 3] set timeout 30 spawn ssh $ipaddress -p$port -l$username expect { "yes/no" { send "yes\r";exp_continue } "password:" { send "$passwd\r" } } expect -re "\](\$|#) " send "touch test \r" expect -re "\](\$|#) " send "exit\r" ? 說明:這里只實現了登錄服務器后在當前目錄創建了一個test文件,具體需求請自行修改添加命令 ? 3、批量執行 其實只要寫好第2步的腳本就可以通過下面命令執行一臺服務器的處理: [root@localhost ~]# expect?dotask.exp?192.168.0.10 22 root 123456 但為了能批量處理n臺,再寫個shell腳本就行了,如下: [root@localhost ~]# vi doexcute.sh #!/bin/bash ? filename="server_list.conf" while read line do ??#echo $line; ??expect?dotask.exp$line done < $filename ? 說明:讀取配置文件,循環執行 最后,其他具體的使用方法參見expect手冊 ? ================================================= 實用工具:autoexpect ================================================= 如果自己懶得寫expect代碼,則可以用autoexpect生成。autoexpect工具是用expect寫成的一個工具腳本,它可以錄制你執行的操作、命令、鍵盤輸入等等,之后自動生成expect腳本。 autoexpect腳本代碼見:http://blog.sina.com.cn/s/blog_5432f2730100vcqn.html 使用方法: 1、把上面鏈接里的autoexpect代碼保存成文件:autoexpect.exp 2、執行下面命令進行錄制: [root@localhost ~]# expect?autoexpect.exp -p ?說明:執行完上面命令后就可以進行你需要的操作了,需要結束錄制時,用exit退出即可。 3、錄制完后,會在當前目錄生成一個script.exp文件,這個文件就是錄制好的expect腳本了。是直接拿來使用,還是再改改,或是學習用,就看你自己的需要了。 |
?
2、在shell語句中完成賦值操作,并做判斷
http://blog.51cto.com/maomaochong/1690753
注意:
1.?if判斷中[]與if間需要有空格;
2.?if判斷語句中判斷語句與[]兩邊都要有空格;
3.?If判斷語句中=號兩邊要有空格;
例如##ping -c 3 -i 0.1 192.168.1.32 && result=0||result=1;if [ "${result}" ?= ?0 ];then echo success;fi
例如:當查看文件中是否有TLSCACertificatePath 開頭的行,若有退出程序,若無則在最后一行加入。
cat sldap.conf|grep ^TLSCACertificatePath && result=0||result=1;echo ${result};if [ "${result}" = 0 ];then exit 1;else sed -i '$a TLSCACertificatePath' sldap.conf;fi
例如:當查看文件中是否有TLSCACertificatePath 開頭的行,若有不做處理,若無則在最后一行加入。
cat sldap.conf|grep ^TLSCACertificatePath && result=0||result=1;echo ${result};if [ "${result}" = 1 ];then sed -i '$a TLSCACertificatePath' sldap.conf;fi
Shell腳本中expect寫入最終格式(注意路徑和轉義):
send "cat $SERVERLDAP_PATH/sldap.conf|grep ^TLSCACertificatePath && result=0||result=1;if \[ \"$\{result\}\" = 1 \];then sed -i '\$a TLSCACertificatePath /usr/local/etc/openldap/certs' $SERVERLDAP_PATH/sldap.conf;fi\r"
五、shell腳本調用expect腳本(即.sh文件調用.exp文件)
| [root@slave1 workspace]# cat test.sh |
| #!/bin/sh ./dotask.exp 192.168.1.93 22 root asdfgh |
| [root@slave1 workspace]# cat dotask.exp |
| 代碼見 四、expect的使用實例1 |
六、shell腳本調用shell腳本(即.sh文件調用.sh文件)
https://blog.csdn.net/simple_the_best/article/details/76285429
| hello.sh |
| #!/bin/bash wor="world" echo "hello `source ./world.sh`" |
| world.sh |
| #!/bin/bash echo $wor |
參考鏈接:
http://blog.sina.com.cn/s/blog_5432f2730100vcql.html
https://www.cnblogs.com/lixigang/articles/4849527.html
https://blog.csdn.net/nero_g/article/details/53945654
總結
以上是生活随笔為你收集整理的shell脚本——expect命令的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: shell脚本——实现简单的功能
- 下一篇: Mysql —— linux下使用c语言