自动交互式脚本--expect

https://www.cnblogs.com/zhuiluoyu/p/4873869.html

我们经常会遇到一些需要与服务器程序打交道的场景,比如,从登陆某个服务器,然后进行某项工作。这很平常,但是如果把这个工作自动化进行,你就需要一个程序能自动做你要告诉机器的事情,这样,我们的expect就能大显身手了。

首先,expect是一个简单的工具语言,如要工作就是进行自动化的人机交互。它的作者对Expect的定义:是一个实现自动交互功能的软件套件(a software suite for automating interactive tools),使用expect,它能帮助我们在合适的情景下进行合适的交互。

例子:我们要在凌晨登陆到一个linux服务器:192.168.1.1,然后执行一个命令做/home/test/a.sh,我们的思路是:写一个expect脚本,然后用crontab在凌晨运行。

1
2
3
4
5
6
7
8
9
10
#!/usr/bin/expect -f
set timeout 30
spawn ssh -l test 192.168.1.1
expect "password:"
send "mypassword\r"
expect "~$*"
send "/home/test/a.sh\r"
send "exit\n"
expect eof
exit

expect 的核心功能,对于设定好的特定匹配形式,以相匹配的动作以应对。每一个expect后所跟的字符串(或者正则表达式)就是脚本所等待的匹配模式,每一个send 所做的工作就是对于各种的模式串,实施相应的动作。

第一行设定了脚本执行的程序,-f选项指的是expect执行一个文件

第二行,设定了本脚本所有的超时时间,单位是秒(s),如果超时,脚本将继续向下进行(比如在等待某个模式出现,超时以后,会进行下一语句)。

第三行,expect使用spawn命令来启动脚本和命令会话,这里启动的是ssh命令,这里的ssh命令将会以子进程的方式产生。

下面就是交互的过程:ssh -l 登陆以后,会给要求客户写入密码,所以等待出现“password:”,出现password:以后,需要写入密码,注意这里需要送去回车或者换行符,否则远端主机不会收到ssh请求的。登陆上系统之后,会出现命令提示符:~$,即系统已经登陆到了远端主机的shell,然后送去要执行的命令。完毕后推出远程机器(这个send "exit\r"前也可以有上一个命令的输出,也可以没有,因为上一个命令执行完毕后会顺序执行下一条)。

最后是等待标示子进程已结束的标示符eof,然后退出。(注:这个等待eof必须要有,如果没有eof,很可能在子进程没有结束前就退出,造成问题。)

下面的例子,介绍expect其他重要的命令,先看如下例子:

1
2
3
4
5
6
7
#!/usr/bin/expect -f
set timeout 10
set myname [lindex $argv 0]
spawn ./talk.sh
expect "Name:"
send "$myname\r"
expect eof

这个例子引入了输入参数的概念,就是在执行这个expect脚本时候,需要带入参数,比如这个脚本名字如果为test.ep

执行时需要键入参数:./test.ep "John"

set myname [lindex $argv 0] 这句获取外部传入的第一个参数(argv 0)并传给变量myname,如果获取多个参数则使用argv 1,argv 2,以此类推。

另外,expect支持一般语言所常用的if,for等流程控制语句,这个可以参看expect高级介绍

小结:

expect是一款非常好用的自动化交互工具

核心命令:

spawn: 启动一个命令或程序,并由expect程序开始监听

set :设置变量值和名称

set .. lindex:从程序输入参数出获取变量值并赋给变量

expect ...send对:expect等待希望出现的匹配串,对于匹配到的串,send发送命令进行执行。

如何向expect脚本里面传递参数

比如下面脚本用来做ssh无密码登陆,自动输入确认yes和密码信息,用户名,密码,hostname通过参数来传递
 
ssh.exp
Python代码  
1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/expect 
set timeout 10 
set username [lindex $argv 0] 
set password [lindex $argv 1] 
set hostname [lindex $argv 2] 
spawn ssh-copy-id -i .ssh/id_rsa.pub $username@$hostname 
expect "yes/no" 
send "yes\r" 
expect "password:" 
send "$password\r"  
expect eof  
执行脚本./ssh.exp root pasword hostname1
expect接收参数的方式和bash脚本的方式不太一样,bash是通过$0 ... $n 这种方式,而expect是通过set <变量名称> [lindex $argv <param index>],例如set username [lindex $argv 0]
 

expect用法

1. [#!/usr/bin/expect]

这一行告诉操作系统脚本里的代码使用那一个shell来执行。这里的expect其实和linux下的bash、windows下的cmd是一类东西。

注意:这一行需要在脚本的第一行。

2. [set timeout 30]

基本上认识英文的都知道这是设置超时时间的,现在你只要记住他的计时单位是:秒   。timeout -1 为永不超时

3. [spawn ssh -l username 192.168.1.1]

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 "ispass\r"]

这里就是执行交互动作,与手工输入密码的动作等效。

温馨提示: 命令字符串结尾别忘记加上“\r”,如果出现异常等待的状态可以核查一下。

6. [interact]

执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。如果你只是登录过去执行

7.$argv 参数数组

expect脚本可以接受从bash传递过来的参数.可以使用[lindex $argv n]获得,n从0开始,分别表示第一个,第二个,第三个....参数

下面的expect脚本的例子

执行这个文件./launch.exp 1 2 3

屏幕上就会分别打印出参数

send_user用来发送内容给用户。

参数运用方面还有很多技巧

比如$argc 存储了参数个数,args被结构化成一个列表存在argv。$argv0 被初始化为脚本名字。

除此之外,如果你在第一行(#!那行)使用-d (debug参数),可以在运行的时候输出一些很有用的信息

比如你会看见

argv[0] = /usr/bin/expect argv[1] = -d argv[2] = ./launch.exp argv[3] = 1 argv[4] = 2 argv[5] = 3

使用这些也可以完成参数传递

8.

expect的命令行参数参考了c语言的,与bash shell有点不一样。其中,$argc为命令行参数的个数,$argv0为脚本名字本身,$argv为命令行参数。[lrange $argv 0 0]表示第1个参数,[lrange $argv 0 4]为第一个到第五个参数。与c语言不一样的地方在于,$argv不包含脚本名字本身。

9. exp_continue的用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/expect -f
 
set ipaddr "localhost"
 
set passwd "iforgot"
 
spawn ssh root@$ipaddr              #spawn   意思是执行命令,expect内命令,shell中不存在
 
expect {
 
"yes/no" { send "yes\r"; exp_continue}
 
"password:" { send "$passwd\r" }
 
}
 
expect "]# "
 
send "touch a.txt\r"                       #意思为发送命令
 
send "exit\r"
 
expect eof
 
exit

exp_continue可以继续执行下面的匹配,简单了许多。还有一点,让我认识到匹配不见得要匹配最后几个字符。

10.拿来小例子

设置变量     set PASSWD   abcd123

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#!/usr/bin/expect -f
 
# Expect script to supply root/admin password for remote ssh server
 
# and execute command.
 
# This script needs three argument to(s) connect to remote server:
 
# password = Password of remote UNIX server, for root user.
 
# ipaddr = IP Addreess of remote UNIX server, no hostname
 
# scriptname = Path to remote script which will execute on remote server
 
# If you username and passwd has not pass the rsa trust, your login will fail.
 
# Usage For example:
 
#  ./sshlogin.exp password 192.168.1.11 who
 
# ------------------------------------------------------------------------
 
# Copyright (c) 2004 nixCraft project <http://cyberciti.biz/fb/>
 
# This script is licensed under GNU GPL version 2.0 or above
 
# -------------------------------------------------------------------------
 
# This script is part of nixCraft shell script collection (NSSC)
 
# Visit http://bash.cyberciti.biz/ for more information.
 
# ----------------------------------------------------------------------
 
# set Variables
 
set password [lrange $argv 0 0]
 
set ipaddr [lrange $argv 1 1]
 
set scriptname [lrange $argv 2 2]
 
set arg1 [lrange $argv 3 3]
 
set timeout -1
 
# now connect to remote UNIX box (ipaddr) with given script to execute
 
spawn ssh yourusername@$ipaddr $scriptname $arg1
 
match_max 100000
 
# Look for passwod prompt
 
expect "*?assword:*"
 
# Send password aka $password
 
send -- "$password\r"
 
# send blank line (\r) to make sure we get back to gui
 
send -- "\r"
 
expect eof
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#!/usr/bin/expect
 
 # 设置超时时间为 60 秒
 
 set timeout  60                                        
 
 # 设置要登录的主机 IP 地址
 
 set host 192.168.1.46
 
 # 设置以什么名字的用户登录
 
 set name root
 
 # 设置用户名的登录密码
 
 set password 123456
 
  
 
 #spawn 一个 ssh 登录进程
 
 spawn  ssh $host -l $name
 
 # 等待响应,第一次登录往往会提示是否永久保存 RSA 到本机的 know hosts 列表中;等到回答后,在提示输出密码;之后就直接提示输入密码
 
 expect {
 
    "(yes/no)?" {
 
        send "yes\n"
 
        expect "assword:"
 
        send "$pasword\n"
 
    }
 
        "assword:" {
 
        send "$password\n"
 
    }
 
 }
 
 expect "#"
 
 # 下面测试是否登录到 $host
 
 send "uname\n"
 
 expect "Linux"
 
 send_user  "Now you can do some operation on this terminal\n"
 
 # 这里使用了 interact 命令,使执行完程序后,用户可以在 $host 终端进行交互操作。
 
 Interact

用expect实现ssh自动登录对服务器进行批量管理

1.实现ssh自动登录完成任务的expect脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/expect -f
 
set ipaddress [lindex $argv 0]
 
set passwd [lindex $argv 1]
 
set timeout 30
 
spawn ssh shellqun@$ipaddress
 
expect {
 
"yes/no" { send "yes\r";exp_continue }
 
"password:" { send "$passwd\r" }
 
}
 
expect "*from*"
 
send "mkdir -p ./tmp/testfile\r"
 
#send "exit\r"
 
expect "#"  命令运行完, 你要期待一个结果, 结果就是返回shell提示符了(是# 或者$)
 
#最后一句第13行的解释:
 
  
 
其实写成 interact 的最大好处是登录后不会退出,而会一直保持会话连接,可以后续手动处理其它任务,请根据实际情况自行选择了。

2.调用login.exp完成批量管理

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
 
for i in `awk '{print $1}' passwd.txt`
 
do
 
j=`awk -v I="$i" '{if(I==$1)print $2}' passwd.txt`
 
expect /root/shell/login.exp $i $j
 
done

linux下的expect的简单用法及举例

1、使用expect前,需要先安装两个rpm包,下载:http://download.csdn.net/detail/wang7dao/4416172

1
2
# rpm -ihv expect-5.43.0-8.el5.i386.rpm
# rpm -ihv expect-devel-5.43.0-8.el5.i386.rpm

2、使用脚本文件的例子--实现自动输密码

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/expect -f
set password 123456
#download
spawn scp root@192.168.1.218:/root/a.wmv /home/yangyz/
set timeout 300
expect "root@192.168.1.218's password:"
set timeout 300
send "$password\r"
set timeout 300
send "exit\r"
expect eof   www.2cto.com 

3、在sh脚本中嵌入expect的例子--通过连上一个公网的服务器再转跳到一个内网的服务器上,用脚本实现不用输密码,直接使用./goto.sh servername

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash
passmsmallq10="a"
passzhsh="a"
passfcwr="b"
passwapfx="c"
passadfx="d"
  
ip1="200.100.10.10"
ip2="10.100.100.70"
ip3="10.100.100.60"
ip4="10.100.100.10"
ip5="10.100.100.20"
  
case $1 in
"zhsh") passstr=$passzhsh ipstr=$ip2 ;;
"fcwr") passstr=$passfcwr ipstr=$ip3 ;;
"wapfx") passstr=$passwapfx ipstr=$ip4 ;;
"adfx") passstr=$passadfx ipstr=$ip5 ;;
*) echo "The parameter $1 isn't exist"
exit 0 ;;  www.2cto.com 
esac
1
2
3
4
5
6
7
8
9
10
11
12
command1="ssh -l m_smallq -p 36000 $ip1"
command2="ssh -l mqq -p 36000 $ipstr"
  
expect -c "
        set timeout 60;
        spawn $command1;
        expect {
                \"221.130.15.10's password:\" {send \"$passmsmallq10\r\"; exp_continue}
                \"m_smallq\" {send \"$command2\r\"; exp_continue}
                \"mqq's password:\" {send \"$passstr\r\";interact}
                }
        "
对上面例子的expect的解说
expect -c "..."  --里面输入命令
expect {...}     --里面的多行记录,从上向下扫描匹配,谁先匹配谁先处理。
  www.2cto.com 

4、ssh到另一台机子执行df -h后退出,要点是send后面可以跟多个命令,通过\r来分行成多个命令

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
ip1="183.62.178.191"
command1="ssh -l root -p 14322 $ip1"
  
expect -c "
        spawn $command1;
        expect {
                \"183.62.178.191's password:\" {send \"aa\r\"; exp_continue}
                \"root@\" {send \"df -h\r exit\r\"; exp_continue}
                }
        "

[转帖]自动交互式脚本--expect的更多相关文章

  1. 自动交互式脚本--expect

    我们经常会遇到一些需要与服务器程序打交道的场景,比如,从登陆某个服务器,然后进行某项工作.这很平常,但是如果把这个工作自动化进行,你就需要一个程序能自动做你要告诉机器的事情,这样,我们的expect就 ...

  2. 交互式脚本expect场景示例

    expect语法示例 #spawn 新建一个进程,这个进程的交互由expect控制 #expect 等待接受进程返回的字符串,直到超时时间,根据规则决定下一步操作 #send 发送字符串给expect ...

  3. linux自动交互工具expect,tcl安装和安装包,以及自动互信脚本

    linux自动交互工具expect,tcl安装,以及自动互信脚本 工作中需要对几十台服务器做自动互信,无意中发现expect命令,研究一番. 在网上找了许多资料也没有安装成功,摸索着总算成功了.现分享 ...

  4. centos shell编程4【分发系统】 服务器标准化 mkpasswd 生成密码的工具 expect讲解 expect传递参数 expect自动同步文件 expect指定host和要同步的文件 expect文件分发系统 expect自动发送密钥脚本 Linux脚本执行方式 第三十八节课

    centos shell编程4[分发系统] 服务器标准化  mkpasswd 生成密码的工具  expect讲解   expect传递参数   expect自动同步文件  expect指定host和要 ...

  5. expect 实现自动交互脚本

    1. 说明 在编写脚本时,可能会遇到需要在另一台主机上执行一个命令,或者在本机拷贝另一台主机内的一个文件.如果两台主机之间没有做互信,就会牵扯到用户输入密码的交互过程,这对编写自动脚本来说, 就行不通 ...

  6. linux自动化交互脚本expect详解set timeout 5是 意思是在expect语句中,5s后超时,不再作出选择。

    linux自动化交互脚本expect详解  更新时间:2020年10月21日 10:13:20   作者:lendsomething     这篇文章主要介绍了linux自动化交互脚本expect的相 ...

  7. SQL Server镜像自动生成脚本

    SQL Server镜像自动生成脚本 镜像的搭建非常繁琐,花了一点时间写了这个脚本,方便大家搭建镜像 执行完这个镜像脚本之后,最好在每台机器都绑定一下hosts文件,不然的话,镜像可能会不work 1 ...

  8. 企业IT管理员IE11升级指南【15】—— 代理自动配置脚本

    企业IT管理员IE11升级指南 系列: [1]—— Internet Explorer 11增强保护模式 (EPM) 介绍 [2]—— Internet Explorer 11 对Adobe Flas ...

  9. mysql 自动备份和nginx自动安装脚本

    一.自动备份Mysql脚本: 如下脚本为mysql自动备份脚本,仅供参考,可以根据实际情况修改. #!/bin/sh #auto backup mysql #wugk #Define PATH定义变量 ...

随机推荐

  1. 将Redis设置为后台启动

    Linux 在执行redis-server  /etc/redis.conf 时默认开启的是一个前台的进程,也就是说启动的redis 就做不了其他的操作了,只有关闭redis 才能做其他的操作.非常的 ...

  2. 0x02 Python logging模块利用配置加载logger

    目录 logging模块利用配置加载logger 方式一模板:logging.config.dictConfig(config_dict) logging模块利用配置加载logger logging. ...

  3. 在系统下文件上传报错:The temporary upload location [/tmp/tomcat.xxx/work/Tomcat/localhost/ROOT] is not valid

    线上的系统中长时间不访问时不能上传文件了,出现如下错误: 2019-03-11 23:37:42.741 ERROR 66505 --- [nio-8081-exec-3] o.a.c.c.C.[.[ ...

  4. XGBoost使用教程(与sklearn一起使用)二

    一.导入必要的工具包# 运行 xgboost安装包中的示例程序from xgboost import XGBClassifier # 加载LibSVM格式数据模块from sklearn.datase ...

  5. Go Programming Language 2

    [Go Programming Language 2] 1.In Go, the sign of the remainder is always the same as the sign of the ...

  6. 用Python玩转微信

    Python玩转微信 大家每天都在用微信,有没有想过用python来控制我们的微信,不多说,直接上干货!  这个是在 itchat上做的封装  http://itchat.readthedocs.io ...

  7. rtmpdump应用在window中

    rtmp.c 中RTMP_GetTime()函数要改成如下: #pragma comment(lib, "winmm.lib ")uint32_tRTMP_GetTime(){// ...

  8. android 8.0 悬浮窗 最简demo

    MainActivity.java文件 package com.example.performance; import android.app.Activity; import android.con ...

  9. rn相关文档

    RN相关文档: rn文档:https://reactnative.cn/ mbox文档:https://cn.mobx.js.org/ es6文档:http://es6.ruanyifeng.com/ ...

  10. Http请求头中 X-Requested-With

    String requestedWith = ((HttpServletRequest) request).getHeader("X-Requested-With"); 如果 re ...