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. cd tcl8.4.11/unix  
  2. ./configure --prefix=/usr/tcl --enable-shared  
  3. make  
  4. make install  

注意:

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.安装配置 

  1. cd expect5.45  
  2. ./configure --prefix=/usr/expect --with-tcl=/usr/tcl/lib --with-tclinclude=../tcl8.4.11/generic  
  3. make  
  4. make install  
  5. ln -s /usr/tcl/bin/expect /usr/expect/bin/expect  

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登录远程服务器并执行命令操作

远程交互从服务器Assh到服务器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

[email protected]'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

猜你喜欢

转载自blog.csdn.net/weixin_42167759/article/details/80708417
今日推荐