Expect 主要应用于自动化交互式操作场景,可以将ssh、ftp、scp等需人工交互的操作写在一个脚本上使之自动化完成。尤其适用于需要对多台服务器执行相同操作的环境中,可以大大提高系统管理人员的工作效率。
其主要交互流程是:
spawn启动指定进程(发送命令) -> expect获取指定关键字 -> send发送回应 -> 执行完成 -> 继续或退出.
expect 是由基于Tcl( Tool Command Language )语言开发的,因此安装前需要安装tcl语言环境。可以使用yum安装或源码安装。
yum install -y tcl
yum install -y expect
rpm -ivh tcl-8.4.13-4.el5.x86_64.rpm
rpm -ivh expect-5.43.0-5.1.x86_64.rpm
解压安装包
tar -zxvf tcl8.4.20-src.tar.gz
tar -zxvf expect5.45.3.tar.gz
安装tcl
cd tcl8.4.20/unix/
./configure --prefix=/usr/tcl --enable-shared
make
make install
cp tclUnixPort.h ../generic
安装expect
cd /root/expect5.45.3/
./configure --prefix=/usr/expect --with-tcl=/usr/tcl/lib --with-tclinclude=/root/tcl8.4.20/generic
make
make install
ln -s /usr/tcl/bin/expect /usr/bin/expect
简单测试
[root@mydb02 ~]# expect
expect1.1> send "hello world\n"
hello world
expect1.1> expect "hi" { send "You said hi\n" } \
+> "hello" { send "Hello yourself\n" } \
+> "bye" { send "That was unexpected\n" }
#输入
hi
#输出
You said hi
完整版可执行 man expect 查看
命 令 | 说 明 |
---|---|
spawn | 启动新的交互进程,后面跟命令或者指定程序 |
expect | 待匹配信息(部分匹配即可)。从进程中接收信息,如果匹配成功,就执行expect后的动作 |
send | 向进程发送字符串或命令 |
exp_continue | 匹配多个字符串在执行动作后加此命令 |
send_user | 打印后跟的字符串内容,相当于shell中的echo |
interact | 执行完命令后保持在交互状态,此时Expect会把控制权交给控制台,变回手工操作。如果只是登录过去执行一段命令就退出,可将其改为 expect eof |
exit | 退出expect脚本 |
eof | expect执行结束, 退出 |
set | 定义变量 |
puts | 输出变量 |
set timeout | 设置超时时间 |
最简单的自动登录脚本
#!/usr/bin/expect
set timeout 30
spawn ssh -l root 172.16.22.131
expect "password*"
send "123456\r"
interact
# 或者 expect eof
#!/usr/bin/expect 必须位于第一行,说明需要使用系统的哪个脚本解析引擎来执行,具体路径根据实际expect 命令实际路径而定。
#!/usr/bin/expect
set ip 172.20.110.199
set user root
set password 123456wht
set timeout 10
spawn ssh $user@$ip
expect "password:"
send "$password\n"
interact
#expect eof
运行结果如下
[root@localhost ~]#./sshbl.exp
spawn ssh 172.20.110.199
root@172.20.110.199's password:
Last login: Sat May 12 11:26:45 2018 from 172.20.110.169
[root@localhost ~]#
#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
interact
#运行 ./ssh3.exp 192.168.8.100 root magedu
批量ssh-copy-id
#!/bin/bash
#用于批量ssh-copy-id 免密码登陆服务器
which expect || yum -y install expect
TXT_PATH=/home/wht/ssh-login/list.txt
ssdzd(){
expect <<-EOF
set timeout 10
spawn ssh-copy-id $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
expect "]#" { send "exit\n" }
expect eof
EOF
}
a=`cat ${TXT_PATH}|wc -l`
echo $a
for i in `seq $a` ; do
echo $i
ip=`cat ${TXT_PATH}|head -n $i|tail -n 1|awk '{print $1}'`
user=`cat ${TXT_PATH}|head -n $i|tail -n 1|awk '{print $2}'`
password=`cat ${TXT_PATH}|head -n $i|tail -n 1|awk '{print $3}'`
ssdzd
done
list.txt
vi exe.expect
#!/usr/bin/expect
set host [lindex $argv 0]
set passwd "xxxx"
spawn ssh myuser@$host
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$passwd\n" }
}
expect "$ "
send "sudo -i\r"
expect "myuser:"
send "$passwd\r"
expect "]# "
send "cd /etc/zabbix/zabbix_agentd.d/zabora/sql\r"
expect "]# "
send "mv test.txt test.txt.bak\r"
expect "]# "
send "exit\r"
#expect eof
expect "~]$ "
send "exit\r"
expect eof
vi test.sh
#!/bin/bash
for ip in `cat ip.txt`
do
./exe.expect $ip
done
ip.txt
执行效果
[root@mydb02 ~]# ./test.sh ip.txt
spawn ssh myuser@192.168.3.225
myuser@192.168.3.225's password:
Last login: Wed Dec 2 19:07:49 2020 from 10.13.3.224
[myuser@mydb03 ~]$ sudo -i
[sudo] password for myuser:
[root@mydb03 ~]# cd /etc/zabbix/zabbix_agentd.d/zabora/sql
[root@mydb03 sql]# mv test.txt test.txt.bak
[root@mydb03 sql]# exit
logout
[myuser@mydb03 ~]$ exit
logout
Connection to 192.168.3.225 closed.
spawn ssh myuser@192.168.3.247
myuser@192.168.3.247's password:
Last login: Wed Dec 2 19:07:50 2020 from 10.13.3.224
[myuser@mydb04 ~]$ sudo -i
[sudo] password for myuser:
[root@mydb04 ~]# cd /etc/zabbix/zabbix_agentd.d/zabora/sql
[root@mydb04 sql]# mv test.txt test.txt.bak
[root@mydb04 sql]# exit
logout
[myuser@mydb04 ~]$ exit
logout
Connection to 192.168.3.247 closed.
[root@mydb02 ~]#
执行 perl adcfgclone.pl dbTechStack 脚本,并输入各种各样的应答
#!/bin/bash
#**********************************************************************************
# Author: Hehuyi_In
# Date: 2022年05月
# FileName: erp_adcfgclone_db_tier.sh
# Dependence: yum install expect -y
# Description: Run adcfgclone.pl script on db tier
# CopyRight (C): 2022 All rights reserved
# example: bash -x erp_adcfgclone_db_tier.sh or ./erp_adcfgclone_db_tier.sh
#**********************************************************************************
ORACLE_SID_UPPER=`echo "$ORACLE_SID" | tr '[:lower:]' '[:upper:]'`
# execute adcfgclone.pl script by expect
erp_adcfgclone_db_tier(){
lsnrctl stop $ORACLE_SID
cd /u01/$ORACLE_SID/db/tech_st/11.2.0/appsutil/clone/bin
expect <<EOF
set timeout -1
spawn perl adcfgclone.pl dbTechStack
expect "APPS password :"
send "xxxxx\r"
expect "Target System Hostname"
send "\r"
expect "RAC (y/n)"
send "\r"
expect "Database SID :"
send "$ORACLE_SID\r"
expect "Base Directory :"
send "/u01/$ORACLE_SID\r"
expect "Directory List :"
send "/tmp\r"
expect "Target System"
send "2\r"
expect "DATA_TOP Directory 1 :"
send "/u01/$ORACLE_SID/db/apps_st/data/${ORACLE_SID_UPPER}/onlinelog\r"
expect "DATA_TOP Directory 2 :"
send "/u01/$ORACLE_SID/db/apps_st/data/${ORACLE_SID_UPPER}/datafile\r"
expect "/u01/$ORACLE_SID/db/tech_st/11.1.0"
send "/u01/$ORACLE_SID/db/tech_st/11.2.0\r"
expect "preserve the Display"
send "n\r"
expect "Target System Display"
send "\r"
expect "source system (y/n)"
send "n\r"
expect "Port Pool"
send "80\r"
EOF
}
# execute the function
erp_adcfgclone_db_tier
参考