用expect脚本实现自动化交互(包含几个经典例子)

expect是建立在tcl基础上的一个工具,它用来让一些需要交互的任务自动化地完成。
因为expect是基于tcl的,所以需要你的系统中安装有tcl

用法

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

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

2. [set timeout 30]

设置超时时间,计时单位:秒。timeout -1 为永不超时,默认情况下,timeout是10秒。

3. [spawn ssh -l username 192.168.1.1]

spawn是进入expect环境后才可以执行的expect内部命令,如果没有装expect或者直接在默认的SHELL下执行是找不到spawn命令的。所以不要用 “which spawn“之类的命令去找spawn命令。
主要功能是用来开始一个新的进程
spawn后面加上需要执行的shell命令,比如说spawn sudo touch testfile.

4. [expect “password:”]

这里的expect也是expect的一个内部命令,功能是判断上次输出结果里是否包含“password:”的字符串,如果有则立即返回,否则就等待一段时间后返回,这里等待时长通过set timeout来设置。

5. [send “ispass\r”]

这里就是执行交互动作,与手工输入密码的动作等效。
***温馨提示: 命令字符串结尾别忘记加上“\r”,如果出现异常等待的状态可以核查一下。

6. [interact]

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

7. [expect eof]

与spawn对应,表示捕捉终端输出信息终止,结束交互。

8. send和send_user

send会将expect脚本中需要的信息发送给spawn启动的那个进程,而send_user只是回显用户发出的信息,类似于shell中的echo而已。

9. exp_continue的用法

使用exp_continue后,会重新从当前expect块的开始重新执行,可以简单理解为while循环的continue.

expect {
          -re "Permission denied, please try again." {
           send_user "Error:Permission denied.\n"
            exit
          }
         -re "Are you sure you want to continue connecting (yes/no)?" {
            send "yes\r";exp_continue
              }
         -re "assword:" {
         send "$loginpass\r";exp_continue
                 }
          -re "Connection refused" {
          			exit
		                    }
        	timeout {
               		 exit
        			}
        	eof {
                	exit
        			}
		}

例子

#1

下面的脚本例子,实现了:登录一个Linux服务器,执行 df -h 等命令。
vi expectExample.sh 后输入下面的脚本内容保存后,使用chmod +x expectExample.sh 命令为脚本赋予可执行权限。

#!/usr/bin/expect -f
#--- set the variable,you can modify the value
set ipaddr [lrange $argv 0 0]
set port [lrange $argv 1 1]
set loginuser [lrange $argv 2 2]
set loginpass [lrange $argv 3 3]
set cmd_prompt "]#|~]?"
#超时时间,单位(秒)
set timeout 3600
#--- login by ssh
spawn ssh -p $port $loginuser@$ipaddr
expect {
        -re "Permission denied, please try again." {
                send_user "Error:Permission denied.\n"
                exit
        }
                -re "Connection refused" {
                send_user "Error:Connection refused.\n"
                exit
        }
        timeout {
                exit
        }
        eof {
                exit
        }
        -re "Are you sure you want to continue connecting (yes/no)?" {
                send "yes\r"
                exp_continue
        }
        -re "assword:" {
                send "$loginpass\r"
                exp_continue
        }
        -re $cmd_prompt {
                send "\r"
        }
}
#--- now,we do some commands
expect {
        -re $cmd_prompt {
                send "df -h\r"
        }
}
expect {
        -re $cmd_prompt {
                send "free -m\r"
        }
}
expect {
        -re $cmd_prompt {
                send "uptime\r"
        }
}
send "cd /opt\r"
send "mkdir shanhy123\r"
send "cd shanhy123\r"
send "echo 123 > 123.txt\r"
send "/opt/xs.sh\r"
send "exit\r"
expect eof
#interact

其中 xs.sh 为一个shell 脚本,里面做了一个sleep 模拟耗时操作,代码如下:

#!/bin/bash
sleep 10
echo abc > /opt/abc.txt

#2

#!/usr/bin/expect

set passwd "mypasswd"
set timeout 60

if {$argc != 1} {
    send "usage ./account.sh \$newaccount\n" 
    exit
}

set user [lindex $argv [expr $argc-1]]

spawn sudo useradd -s /bin/bash -g mygroup -m $user

expect {
    "assword" {
        send_user "sudo now\n"
        send "$passwd\n"
        exp_continue
    }
    eof
    {
        send_user "eof\n"
    }
}

spawn sudo passwd $user
expect {
    "assword" {
        send "$passwd\n"
        exp_continue
    }
    eof
    {
        send_user "eof"
    }
}

spawn sudo smbpasswd -a $user
expect {
    "assword" {
        send "$passwd\n"
        exp_continue
    }
    eof
    {
        send_user "eof"
    }
}

第3行: 对变量赋值的方法;
第4行: 默认情况下,timeout是10秒;
第6行: 参数的数目可以用 a r g c 得 到 ; 第 11 行 : 参 数 存 在 argc得到; 第11行:参数存在 argc11argv当中,比如取第一个参数就是[lindex $argv 0];并且如果需要计算的话必须用expr,如计算2-1,则必须用[expr 2-1];
第13行:用spawn来执行一条shell命令,shell命令根据具体情况可自行调整;有文章说sudo要加-S,经过实际测试,无需加-S亦可;
第15行:一般情况下,如果连续做两个expect,那么实际上是串行执行的,用例子中的结构则是并行执行的,主要是看匹配到了哪一个;在这个例子中,如果你写成串行的话,即

expect "assword"
send "$passwd\n"
expect eof
send_user "eof"

那么第一次将会正确运行,因为第一次sudo时需要密码;但是第二次运行时由于密码已经输过(默认情况下sudo密码再次输入时间为5分钟),则不会提示用户去输入,所以第一个expect将无法匹配到assword,而且必须注意的是如果是spawn命令出现交互式提问的但是expect匹配不上的话,那么程序会按照timeout的设置进行等待;可是如果spawn直接发出了eof也就是本例的情况,那么expect "assword"将不会等待,而直接去执行expect eof。 这时就会报expect: spawn id exp6 not open,因为没有spawn在执行,后面的expect脚本也将会因为这个原因而不再执行;所以对于类似sudo这种命令分支不定的情况,最好是使用并行的方式进行处理;
第17行:仅仅是一个用户提示而已,可以删除;
第18行:向spawn进程发送password;
第19行:使得spawn进程在匹配到一个后再去匹配接下来的交互提示;
第21行:eof是必须去匹配的,在spawn进程结束后会向expect发送eof;如果不去匹配,有时也能运行,比如sleep多少秒后再去spawn下一个命令,但是不要依赖这种行为,很有可能今天还可以,明天就不能用了;

#3

下面这个例子比较特殊,在整个过程中就不能expect eof了:

#!/usr/bin/expect
set timeout 30
spawn ssh 10.192.224.224
expect "password:"
send "mypassword\n"
expect "*$"
send "mkdir tmpdir\n"
expect "*$"

timeout指expect等待命令至多等30seconds
这个例子实际上是通过ssh去登录远程机器,并且在远程机器上创佳一个目录,我们看到在我们输入密码后并没有去expect eof,这是因为ssh这个spawn并没有结束,而且手动操作时ssh实际上也不会自己结束除非你exit;所以你只能expect bash的提示符,当然也可以是机器名等,这样才可以在远程创建一个目录。

注意,请不要用spawn mkdir tmpdir,这样会使得上一个spawn即ssh结束,那么你的tmpdir将在本机建立。

当然实际情况下可能会要你确认ssh key,可以通过并行的expect进行处理,不多赘述。

#4

最后一个demo是自己尝试写的,功能是安装python3.6.比较简单粗暴,就是用spawn来开启不同的进程,并一直保持交互状态.这样做的原因是之前仿写的时候,使用send来执行指令总是有一些问题.后来发现这样写下来也能work.暂时不知道优缺点,先贴上来请各位指教.

#!/usr/bin/expect
set timeout 30
spawn apt-get install -y software-properties-common
interact
spawn add-apt-repository ppa:deadsnakes
expect "ENTER"
send "\n"
interact
spawn apt-get update
interact
spawn apt-get install python3.6 -y
interact

转载自:
https://blog.csdn.net/weixin_33714884/article/details/92229273
https://my.oschina.net/u/2324318/blog/863281
https://www.cnblogs.com/netflix/p/12122750.html
有部分改动

  • 0
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值