expect安装和使用
Expect是一个我们常在shell交互时常用到的工具,它主要由expect-send组成。Expect是等待输出内容中的特定字符。然后由send发送特定的相应。Expect的工作流程类似于:小明和小红说:hello,小红发现小明说的是hello,然后就回复小明hi。然后小明说:你好,我是小明。小红发现小明说的是”你好,我是XX“,就回复”你好,我是小红“。
本文主要内容: 1.安装expect 2 expect的一些基本命令选项 3 expect脚本
1. 安装expect
1.1 yum 安装
yum安装就比较简单了,直接运行yum install expect就可以了.
yum install expect
1.2 源码安装
源码安装前我们需要安装unzip和gcc
yum install unzip gcc -y
源码安装我们需要下载两个源码包。tcl源码包和expect源码包。
下载tcl源码包
cd /tmp &&wget http://core.tcl.tk/tcl/zip/release/tcl.zip
下载expect源码包
wget https://jaist.dl.sourceforge.net/project/expect/Expect/5.45.3/expect5.45.3.tar.gz
我们需要先编译安装tcl,因为expect包依赖于tcl。
解压压缩包并编译安装tcl
unzip tcl.zip && cd ./tcl/unix
./configure && make && make install
解压压缩包并编译安装expect.
cd /tmp && tar -xzvf expect5.45.3.tar.gz && cd expect5.45.3/
./configure && make && make install
检查是否安装好(显示安装好的版本号就是已经安装好了)并创建软链接。
expect -v
[root@localhost shell]# expect -v
expect version 5.45.3
[root@localhost shell]# ln -s /usr/local/bin/expect /usr/bin/expect
2.expect常用的参数选项
2.1 使用 -c 选项:在命令行运行expect 脚本。
示例:
[root@localhost shell]# expect -c 'expect "hi expect" {send "hi shell\n"}'
hi expect
hi shell
[root@localhost shell]#
解释下:这个的意思就是当我们输入了"hi expect"后,系统输出"hi shell"表示回应,在"hi shell"后加"\n"是为了让显示更为直观。
注意一点就是我们在输入完"hi expect"后要按换行键才会出来"hi shell".
2.2 使用 -d 选项:显示调试信息。
示例脚本:
[root@localhost shell]# cat ssh.exp
#!/usr/bin/expect -d
set timeout
spawn ssh-copy-id 192.168.123.218
expect {
"*yes/no" {send "yes\r"; exp_continue}
"password:" {send "123456\r"}
}
expect eof
当我运行它的时候,显示的信息(主要信息是加粗字体):
expect version 5.45
argv[] = /usr/bin/expect argv[] = -d argv[] = ./ssh.exp
set argc
set argv0 "./ssh.exp"
set argv ""
executing commands from command file ./ssh.exp
spawn ssh-copy-id 192.168.123.218
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {} expect: does "" (spawn_id exp6) match glob pattern "*yes/no"? no
"password:"? no
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub" expect: does "/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"\r\n" (spawn_id exp6) match glob pattern "*yes/no"? no
"password:"? no
The authenticity of host '192.168.123.218 (192.168.123.218)' can't be established.
ECDSA key fingerprint is SHA256:Qh+4R5mpwlU6kK3bf0k53ngm+WpKKnfvL1ZJo+YM3ic.
ECDSA key fingerprint is MD5:d2::6d:::e1::::aa::ce:f7:1f:9f:.
Are you sure you want to continue connecting (yes/no)?
expect: does "/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"\r\nThe authenticity of host '192.168.123.218 (192.168.123.218)' can't be established.\r\nECDSA key fingerprint is SHA256:Qh+4R5mpwlU6kK3bf0k53ngm+WpKKnfvL1ZJo+YM3ic.\r\nECDSA key fingerprint is MD5:d2:76:6d:33:17:e1:51:83:13:aa:10:ce:f7:1f:9f:32.\r\nAre you sure you want to continue connecting (yes/no)? " (spawn_id exp6) match glob pattern "*yes/no"? yes
expect: set expect_out(,string) "/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"\r\nThe authenticity of host '192.168.123.218 (192.168.123.218)' can't be established.\r\nECDSA key fingerprint is SHA256:Qh+4R5mpwlU6kK3bf0k53ngm+WpKKnfvL1ZJo+YM3ic.\r\nECDSA key fingerprint is MD5:d2:76:6d:33:17:e1:51:83:13:aa:10:ce:f7:1f:9f:32.\r\nAre you sure you want to continue connecting (yes/no"
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"\r\nThe authenticity of host '192.168.123.218 (192.168.123.218)' can't be established.\r\nECDSA key fingerprint is SHA256:Qh+4R5mpwlU6kK3bf0k53ngm+WpKKnfvL1ZJo+YM3ic.\r\nECDSA key fingerprint is MD5:d2:76:6d:33:17:e1:51:83:13:aa:10:ce:f7:1f:9f:32.\r\nAre you sure you want to continue connecting (yes/no"
send: sending "yes\r" to { exp6 }
expect: continuing expect expect: does ")? " (spawn_id exp6) match glob pattern "*yes/no"? no
"password:"? no
yes expect: does ")? yes\r\n" (spawn_id exp6) match glob pattern "*yes/no"? no
"password:"? no
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed expect: does ")? yes\r\n/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed\r\n" (spawn_id exp6) match glob pattern "*yes/no"? no
"password:"? no
/usr/bin/ssh-copy-id: INFO: key(s) remain to be installed -- if you are prompted now it is to install the new keys expect: does ")? yes\r\n/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed\r\n/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys\r\n" (spawn_id exp6) match glob pattern "*yes/no"? no
"password:"? no
root@192.168.123.218's password:
expect: does ")? yes\r\n/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed\r\n/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys\r\nroot@192.168.123.218's password: " (spawn_id exp6) match glob pattern "*yes/no"? no
"password:"? yes
expect: set expect_out(,string) "password:"
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) ")? yes\r\n/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed\r\n/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys\r\nroot@192.168.123.218's password:"
send: sending "123456\r" to { exp6 }
Number of key(s) added:
Now try logging into the machine, with: "ssh '192.168.123.218'"
and check to make sure that only the key(s) you wanted were added.
expect: read eof
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) " \r\n\r\nNumber of key(s) added: 1\r\n\r\nNow try logging into the machine, with: "ssh '192.168.123.218'"\r\nand check to make sure that only the key(s) you wanted were added.\r\n\r\n"
还有一些其他参数,但是我觉得对于我用处不大,所以没有在此记录。
3.expect脚本示例
简单在这记录下下面会用到的一些命令
set timeout #设置超时时间,默认超时时间10s.
spawn shell command # spawn后面接的是我们要执行的shell命令
expect "hi" #匹配输出内容“hi”
{send “hello\r”} # 匹配到内容''hi"后输出“hello”,“\r”是代表是返回字符。
interact #执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。如果你只是登录过去执行一段命令就退出,可改为[expect eof]
3.1 简单更改密码脚本
[root@localhost shell]# cat password.exp
#!/usr/bin/expect -d #"#!/usr/bin/expect"这一行告诉操作系统脚本里的代码使用那一个shell来执行。 -d 启用调试模式(可加可不加)。
set timeout 30 #设置超时时间为30s
spawn passwd user5 #spawn是进入expect环境后才可以执行的expect内部命令,如果没有装expect或者直接在默认的SHELL下执行是找不到spawn命令的。所以不要用 “which spawn“之类的命令去找spawn命令。好比windows里的dir就是一个内部命令,这个命令由shell自带,你无法找到一个dir.com 或 dir.exe 的可执行文件。它主要的功能是给ssh运行进程加个壳,用来传递交互指令。
expect "New password:" {send "123456\r" } #这个命令的意思是判断上次输出结果里是否包含“New password:”的字符串,如果有则立即返回"123456","\r"代表是返回字符,否则就等待一段时间后返回,这里等待时长就是前面设置的30秒 。
expect "new password:" {send "123456\r"} #在平常我们设置密码的时候会让我输入一次后再输入一次进行确认,这个是匹配第二次输出,然后再次输入密码。
expect eof #表示读取到文件结束符
3.2登陆远程服务器并停留在远程服务器上
[root@localhost shell]# cat login.exp
#!/usr/bin/expect
spawn ssh 192.168.123.218 #ssh 远程登陆
expect {
"*yes/no" {send "yes\r";exp_continue} #匹配输出内容,返回内容,exp_continue表示继续执行下一步
"*password" {send "123456\r"}
}
interact #执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。如果你只是登录过去执行一段命令就退出,可改为[expect eof]
3.3传输参数执行登陆
[root@localhost shell]# cat login2.exp
#!/usr/bin/expect
set ip [lindex $argv ] #这条命令是将变量ip的值设置为传入进来的第一个参数。[lindex $argv 0]表示的就是第一个参数的值
set port [lindex $argv ] #这条命令是将变量port的值设置为传入进来的第二个参数。[lindex $argv 1]表示的就是第二个参数的值
set passwd ""
spawn ssh $ip -p$port #使用变量,这里使用的方法跟shell脚本一样
expect {
"yes/no" {send "yes\r";exp_continue}
"password:" {send "$passwd\r"}
}
interact
[root@localhost shell]# ./login2.exp 192.168.123.218 22 #多个参数直接以空格间隔,第一个参数:192.168.123.218 第二个参数22
3.4在shell脚本中使用expect
3.4.1通过添加expect脚本文件(建议这种)
实现的功能:输入ip(也就是我们传入的参数),并登陆到这个ip,并保持交互状态(interact)。
login.sh脚本内容(shell)
[root@localhost shell]# cat login.sh
#!/bin/bash
read -p "please input you ip:" -t30 remote_ip #获取登陆ip内容
echo "$remote_ip"
./login.exp $remote_ip #运行expect脚本 传入参数
login.exp脚本内容(expect)
[root@localhost shell]# cat login.exp
#!/usr/bin/expect
set ip [lindex $argv ] #将参数值传递给变量ip
spawn ssh $ip #登陆ip
expect {
"*yes/no" {send "yes\r";exp_continue} #匹配登陆信息,返回'yes'
"*password" {send "123456\r"} #匹配输出信息,返回密码
}
interact #登陆成功后并保持交互状态,把控制权交给控制台
3.4.2在shell脚本直接写入expect命令
#!/bin/bash
read -p "please input you ip:" -t30 remote_ip #获取登陆ip内容
echo "$remote_ip"
expect -d <<EOF
spawn ssh $remote_ip
expect {
"*yes/no" {send "yes\r";exp_continue}
"*password:" {send "Xuansiwei123!\r"}
}
exit
expect eof;
EOF
3.4.3 expect匹配不同情况(有密钥文件则退出,没有则添加)
sshkey.exp #!/usr/bin/expect -d
spawn ssh-keygen
expect {
".ssh/id_rsa" {send "\r";exp_continue}
"Overwrite (y/n)?" exit #判断是否已经有密钥文件,有则退出,没有就进行添加。
"Enter passphrase" {send "\r";exp_continue}
"Enter same passphrase again:" {send "\r"}
}
expect eof
3.5批量分发公钥到远程主机
批量分发我主要有三个文件,第一个是ip.txt(用来储存ip和密码的,ip和密码直接以":"间隔,示例:192.168.123.12:123456),第二个文件是add.sh(包含读取ip.txt和批量添加的脚本),第三个文件是 ssh_copy.exp(用来处理交互的脚本)
ip.txt文件内容
#ip password
192.168.123.110:
192.168.123.111:@!
这里注意下我第二行的ip的密码的最后一位是“!”,它在我shell脚本中的取出密码步骤也给我造成了一点麻烦,直接echo "$i"是报错的,我后面换成了echo "${i}",这样就不会报错了。
add.sh(shell脚本)
#!/bin/bash
IP_file='/root/shell/ip.txt'
if [ -e "$IP_file" ] #检查ip.txt文件是否存在,
then
echo -e "\033[1;32;40m IP file is exist \033[0m"
else
echo -e "\033[1;31;40m IP file is not exist \033[0m"
exit
fi
for i in $(cat ${IP_file})
do
IP=$(echo "${i}" |awk -F":" '{print $1}') #将ip.txt每行的ip值获取
PW=$(echo "${i}" |awk -F":" '{print $2}')#将ip.txt每行的ip值获取
./ssh_copy.exp $IP $PW
if [ $? -eq ] #判断expect脚本是否执行成功
then
echo "$IP add is ok "
else
echo "$IP add faile"
fi
done
在上面的shell脚本我们还可以再加一个验证是否添加成功了,通过验证是否可以直接ssh登录来判断是否添加成功。
ssh_copy.exp(expect脚本)
#!/usr/bin/expect #调试的时候可以加个-d参数,便于查看我们的哪里步骤出现了错误。
set IP [lindex $argv ]
set PW [lindex $argv ]
spawn ssh-copy-id $IP
expect {
"yes/no" {send "yes\r";exp_continue}
"password:" {send "$PW\r"}
}
expect eof
这篇文章参考以下大佬的文章。
https://www.cnblogs.com/lixigang/articles/4849527.html
https://segmentfault.com/a/1190000002564816
expect安装和使用的更多相关文章
- linux tcl expect 安装(转)
linux tcl expect 安装 一.Tcl安装 1. 下载:tcl8.4.20-src.tar.gz http://www.tcl.tk/software/tcltk/downloadnow ...
- Expect安装方法
Expect安装方法 http://bluethink.iteye.com/blog/1079044 Tcl脚本SSHITeyeUnix Expect是基于Tcl语言的一种脚本语言,其实无论是交互还 ...
- RHEL6非交互式工具sshpass和expect安装
RHEL6非交互式工具sshpass和expect安装 1 sshpass 在rhel6.4上,没有sshpass的软件包,无法采用yum方式安装.从源码编译安装非常简单. 1) 下载sshpass源 ...
- 【转】CentOS下expect 安装
Expect是在Tcl基础上创建起来的,它还提供了一些Tcl所没有的命令,它可以用来做一些linux下无法做到交互的一些命令操作,在远程管理方面发挥很大的作用. spawn命令激活一个Unix程序 ...
- centos7 自动交互expect 安装使用
1.安装 https://www.cnblogs.com/rocky-AGE-24/p/7256800.html 安装expect命令 两种方式yum安装 yum -y install expect ...
- expect安装去测试
1.下载expect和tcl 下载地址:http://download.csdn.net/download/tobyaries/5754943 2.安装expect tar -zxvf tcl8.4. ...
- Expect 安装 on centos7
本文演示如何在CentOS7上安装和使用Expect. 使用场景 在主机A上编写并且执行Shell脚本,Shell脚本中需要ssh到主机B上执行交互命令. 安装 在主机A上安装expect: yum ...
- expect 安装使用
expect 命令相当于crt远程连接,可用于脚本化实现多服务器巡检功能. 一.expect 命令安装: 1.rpm 文件下载:百度云链接:http://pan.baidu.com/s/1sl1wSU ...
- expect安装测试-批量用户管理
安装: yum list | grep expect yum install expect 批量创建用户: ansible mysqldb -m user -a 'name=ansible state ...
随机推荐
- Delphi Dll 动态调用例子(1)
http://blog.sina.com.cn/s/blog_62c46c3701010q7h.html 一.编写dll library TestDllByD2007; uses SysUtils, ...
- Android-Thread线程的状态
介绍Thread线程的状态之前,必须要讲解CPU执行线程的随机性: 例如:有五个线程,CPU中央处理器,在执行这五个线程的时候,有可能先执行Thread-0,有可能先执行Thread-3,等等,都有可 ...
- zookeeper集群崩溃处理
今天在私有化项目中遇到如下问题: 1.客户反馈用户登录返回303 2.登录服务器查看是大量的log将服务器磁盘空间占用殆尽,导致所有服务进程仍旧存在但是监听端口失败,服务不可用 3.清理日志文件 4. ...
- saprk2 structed streaming
netcat (windows) >nc -L -p 9999 import java.sql.Timestamp import org.apache.spark.sql.SparkSessio ...
- [ACM_数据结构] Color the ball [线段树水题][数组开大]
Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球a开始到气球b依次 ...
- AOP编程的学习总结
前几天听到一个同事说起AOP 然后就想学习下应用到项目中去,自己也是在网上找了很多的资料,之后发现 网上的大部分资料的内容几乎都是如出一撤,于是自己就整理了一下再加上这几天的学习总结到的知识写到这篇文 ...
- Ruby on Rails 目录结构
目录结构 + app/ #控制器.模型.视图.帮助方法.邮件.静态资源 + bin/ #rails脚本 + config/ #路由.数据库等 + db/ #数据库模式.迁移文件 + lib/ #扩展模 ...
- ASP.NET Core使用EF Core操作MySql数据库
ASP.NET Core操作MySql数据库, 这样整套环境都可以布署在Linux上 使用微软的 Microsoft.EntityFrameworkCore(2.1.4) 和MySql出的 MySql ...
- C#在dataGridView中遍历,寻找相同的数据并定位
1. C#在dataGridView中遍历,寻找相同的数据并定位 [c-sharp] view plain copy int row = dataGridView1.Rows.Count;// ...
- Win(Phone)10开发第(1)弹,桌面和手机的扩展API,还我后退键
喜大普奔的win10 uap开发预览版终于出了,这次更新跟8.1的变化不是很大,但是将原本win8.1和wp8.1uap的分项目的形式,改为了整合成一个项目,经过一次编译打包成一个appx包,实现了无 ...