spawn....expect简介及遇到的坑

为什么使用spawn expect …

很多时候,指令的执行是需要交互的,比如下面这个命令大家一定很熟悉:

ssh-keygen -t rsa
# 以及
ssh-copy-id -i /home/xxx/.ssh/id_rsa.pub $username@$host_name

这里需要按三次回车键,或输入yes/no,以及密码才可以.当然,还是那句话单点操作随意,如果一项工作重复次数超过2次,那么我们就应该用脚本来管理它,比如我们要在一个集群规模的每个节点都进行上面的操作,那真的是会很累很累…

expect

expect是一款免费的工具,可以实现自动的交互式任务,无需人工干预.
它可以根据程序的提示信息,来模拟标准输入,提供给程序,以此来实现自动化交互执行的目的.

yum provides expect
# 或直接安装
yum install -y expect

expect命令

命令 作用
spawn 启动一个新的进程,用来执行后面所接的COMMAND
expect 期待从进程中获取的内容
send 向进程发送内容
set timeout n 设置超时时间,单位:,超过n秒则不再继续等待进程的内容返回
interact 是否保留交互状态

命令演示

expect脚本文件的头信息与bash不同,这里需要注意
在这里强烈建议大家养成脚本注释的习惯,日后真的非常有用.

#!/usr/bin/expect
#    Program:
#        run the basic test of expect
#    2020/01/19    Shuu    First release
spawn ssh test
expect "yes/no"
send "yes\r"
expect "password*"
send "test\r"
expect eof

上面的例子,我创建了一个test用户,密码也是test,来进行测试.
执行之后虽然命令提示符会显示test@xxxxxx
在这里插入图片描述
但是执行whoami命令后,会发生改变,而且执行结果并不是test用户.
那么如果想继续留在test用户下进行操作该怎么办呢?interact的作用来了

#!/usr/bin/expect
#    Program:
#        run the basic test of expect
#    2020/01/19    Shuu    First release
spawn ssh test
expect "yes/no"
send "yes\r"
expect "password*"
send "test\r"
interact

仅修改最后一行的expect eof为interact即可.将.ssh目录删掉,再次运行

rm -rf ~/.ssh

在这里插入图片描述
上面的内容还可以用另一种方式来书写:
Pattern—— Action:模式和动作,模式可以有多种,每匹配到一种模式进行相应的动作.

#!/usr/bin/expect
#    Program:
#        run the basic test of expect
#    2020/01/19    Shuu    First release
spawn ssh test
expect {
    "yes/no" {send "yes\r";exp_continue}
    "password*" {send "test\r"}
}
expect eof
# or
# interact

exp_continue,表示继续进行余下的模式匹配,除最后一个一般都要加,否则没必要写那么多Pattern不是吗.

在shell脚本中使用expect

由于expect与bash不同,(从表头就能看出),所以在shell脚本中是不能直接使用spawn ... expect的.
具体写法如下:

#!/bin/bash
#        Program:
#            details
#    yyyy/MM/dd Author release
/usr/bin/expect <<EOF
    spawn ssh-copy-id -i /home/hadoop/.ssh/id_rsa.pub $username@$host_name
    expect {
        "yes/no" {send "yes\r";exp_continue}
        "password" {send "$password\r"}
    }
    expect eof
EOF

这里的/usr/bin/expect会进入expect命令行交互模式
在这里插入图片描述
而后面的 <<EOF表示知道接收到EOF字符为止,一直接收输入内容,当接收到EOF字符时,结束本次expect操作.
!!!这里是个坑重要的事情说三遍:
EOF前后一定不能有空格
EOF前后一定不能有空格
EOF前后一定不能有空格
所以,对代码缩进格式有着强迫症的同学要注意啦!!!
最后一行那个EOF一定要在起始位置,不能有空格!!!

发布了62 篇原创文章 · 获赞 3 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Leonardy/article/details/104040036
今日推荐