先來看一段代碼:
- #!/usr/bin/expect
- set timeout 30
- spawn ssh -l root 192.168.1.188
- expect "password:"
- send "abc123456\r"
- interact
對這6行進行下解釋:
第1行[#!/usr/bin/expect]
這一行告訴操作系統腳本裡的代碼使用那一個shell來執行。這裡的expect其實和linux下的bash、windows下的cmd是一類東西。 這一行需要在腳本的第一行。
第2行[set timeout 30]
基本上認識英文的都知道這是設置超時時間的,現在你只要記住他的計時單位是:秒
第3行 [spawn ssh -l username 192.168.1.188]
spawn是進入expect環境後才可以執行的expect內部命令,如果沒有裝expect或者直接在默認的SHELL下執行是找不到spawn命 令的。所以不要用 “which spawn“之類的命令去找spawn命令。好比windows裡的dir就是一個內部命令,這個命令由shell自帶,你無法找到一個dir.com 或 dir.exe 的可執行文件。 它主要的功能是給ssh運行進程加個殼,用來傳遞交互指令。
第4行[expect "password:"]
這裡的expect也是expect的一個內部命令,有點暈吧,expect的shell命令和內部命令是一樣的,但不是一個功能,習慣就好了。這個命 令的意思是判斷上次輸出結果裡是否包含“password:”的字符串,如果有則立即返回,否則就等待一段時間後返回,這裡等待時長就是前面設置的30 秒
第5行[send "abc123456\r"]
這裡就是執行交互動作,與手工輸入密碼的動作等效。
溫馨提示: 命令字符串結尾別忘記加上“\r”,如果出現異常等待的狀態可以核查一下。
第6行[interact]
執行完成後保持交互狀態,把控制權交給控制台,這個時候就可以手工操作了。如果沒有這一句登錄完成後會退出,而不是留在遠程終端上。
在Linux下,執行ssh登陸或者是scp復制文件的時候可以使用到該命令,實現自動輸入密碼。
案例1:遠程執行命令
- #!/usr/bin/expect -f
- set timeout 30
- spawn ssh -l root 192.168.1.188
- expect {
- "yes/no" { send "yes\r";exp_continue }
- "password:" { send "abc123456\r" }
- }
- expect -re "\](\$|#) "
- send "bash /root/test.sh \r"
- expect -re "\](\$|#) "
- send "exit\r"
該代碼的功能是執行遠程服務器上的/root/test.sh腳本,參數“-re”是匹配正則表達式。可以寫多行send,執行多個命令。該腳本的另一種寫法
- #!/bin/bash
- expect -c "
- spawn ssh [email protected] \"ifconfig;whoami;pwd;echo hello;\"
- expect {
- \"*assword\" {set timeout 30; send \"abc123456\r\";}
- \"yes/no\" {send \"yes\r\"; exp_continue;}
- }
- expect eof
- "
參數“-c”是指在命令行執行expect。把要執行的命令用分號隔開了。並且執行過程中沒有shell提示符的,有興趣的你可以測試下。
案例2:批量處理
在需要管理大量的Linux服務器時,可以這樣做:
1.host.list
- 192.168.1.1 22 root abc1
- 192.168.1.2 22 root abc2
- 192.168.1.3 22 root abc3
- 192.168.1.4 22 root abc4
- 192.168.1.5 22 root abc5
- 192.168.1.6 22 root abc6
- 192.168.1.7 22 root abc7
- 192.168.1.8 22 root abc8
我們把服務器的IP地址、端口號、用戶名、密碼一起放在host.list文件裡,按行排列。
下面來看看腳本文件main.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 "bash /root/test.sh \r"
- expect -re "\](\$|#) "
- send "exit\r"
來做一個while循環:whi.sh
- #!/bin/bash
- host="host.list"
- while read line
- do
- expect main.exp $line
- done < $host
把以上腳本都賦予執行權限,就可以了。
案例3:scp文件傳輸
- expect -c "
- spawn scp [email protected]:/root/file1.tgz /root
- expect {
- \"*assword\" {set timeout 300; send \"abc123456\r\";}
- \"yes/no\" {send \"yes\r\"; exp_continue;}
- }
- expect eof
- "
同樣的原理,也可以做循環進行批量管理,還可以更簡化腳本,也不多說明了,有興趣的同學可以多嘗試下。使用expect進行自動輸入密碼登陸,基本多用於批量管理。也還算方便。關於批量管理有多種方法,可以在主機之間建立ssh信任機制,也可以免密碼登陸管理等。還可以使用sshpass(外部命令)這個命令進行帶密碼在腳本裡執行自動輸入密碼。