笔记内容:

  • 20.28 expect脚本远程登录
  • 20.29 expect脚本远程执行命令
  • 20.30 expect脚本传递参数
  • 20.31 expect脚本同步文件
  • 20.32 expect脚本指定host和要同步的文件

笔记日期:2017-11-29

<br />

expect简介

expect是一个自动化交互式应用程序的工具,所以expect可以用来处理交互的命令。借助expect,我们可以将交互过程写在一个脚本上,使之自动化完成。形象的说,ssh登录,ftp登录等都符合交互的定义。expect含有利用正则表达式进行模式匹配以及通用的编程功能,允许简单的脚本智能地管理如下工具:telnet,ftp和ssh(这些工具都缺少编程的功能),宏以及其它程序。expect脚本的出现使得这些老的软件工具有了新的功能和更多的灵活性。

<br />

expect脚本远程登录

以上简介中也提到了expect和shell类似,可以进行编程,接下来就实际的编写一些expect脚本来学习expect简单的使用方式。

如果你的系统没有安装expect,需要先安装expect,安装命令如下: > yum install -y expect

expect示例:编写一个自动远程登录脚本,expect编写的脚本文件后缀名为expect,这是为了好区分:

[root@localhost ~]# mkdir expectFiles
[root@localhost ~]# cd expectFiles/
[root@localhost ~/expectFiles]# vim telnet_ept.expect
#! /usr/bin/expect
# 需要登录的IP
set host "192.168.77.128"
# 密码
set passwd "123456"
# 登录的命令
spawn ssh root@$host
# expect用于执行一些命令
expect {
# 初次登录会询问"yes/no",所以如果截取的是"yes/no"就 send 发送一个yes,\r是回车的意思,exp_continue表示继续
"yes/no" { send "yes\r"; exp_continue}
# 如果截取的是"password:"就 send 发送密码
"password:" { send "$passwd\r" }
}
# 结束标识,但是不会退出登录,不加interact的话就会马上退出登录
interact

set是用来定义一个变量的,变量名后面跟的就是变量的值,不需要使用等于号来赋值,调用变量的方式和shell一样,也是使用$符号。

与interact相对的就是expect eof ,expect eof会在登录后,停留登录状态1-2秒后才退出登录。

执行这个脚本需要加一个执行权限,然后直接执行就可以了:

[root@localhost ~/expectFiles]# chmod a+x telnet_ept.expect 
[root@localhost ~/expectFiles]# ./telnet_ept.expect 
spawn ssh root@192.168.77.128
The authenticity of host '192.168.77.128 (192.168.77.128)' can't be established.
ECDSA key fingerprint is 4d:5a:9d:31:65:75:30:47:a3:9c:f5:56:63:c4:0f:6a.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.77.128' (ECDSA) to the list of kNown hosts.
root@192.168.77.128's password: 
Last login: Wed Nov 29 14:07:45 2017 from 192.168.77.1
[root@localhost ~]#

运行结果如上,成功登录了192.168.77.128。

<br />

expect脚本远程执行命令

除了能够实现远程登录外,还能实现远程执行命令,例如可以写一个自动远程登录后,执行命令并退出的脚本:

[root@localhost ~/expectFiles]# vim telnet_2.expect
#!/usr/bin/expect
set user "root"
set passwd "123456"
spawn ssh $user@192.168.77.128

expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
# 当遇到 "]#" 就执行sebd命令,我们登录后不就是:[root@localhost ~]#,末尾就是 ]# ,而send是发送touch创建文件的命令
expect "]#"
send "touch /tmp/12.txt\r"
# 同样的当遇到 "]#" 就执行sebd里的命令
expect "]#"
send "echo 1212 &gt; /tmp/12.txt\r"
# 最后退出系统
expect "]#"
send "exit\r"

运行脚本:

[root@localhost ~/expectFiles]# chmod a+x telnet_2.expect 
[root@localhost ~/expectFiles]# ./telnet_2.expect
spawn ssh root@192.168.77.128
root@192.168.77.128's password: 
Last login: Wed Nov 29 14:54:34 2017 from 192.168.77.130
[root@localhost ~]# touch /tmp/12.txt
[root@localhost ~]# echo 1212 &gt; /tmp/12.txt
[root@localhost ~]# 
[root@localhost ~/expectFiles]#

然后再来看看192.168.77.128机器上有没有/tmp/12.txt 文件:

[root@localhost ~]# ll /tmp/12.txt 
-rw-r--r-- 1 root root 5 11月 29 15:10 /tmp/12.txt
[root@localhost ~]# cat !$
cat /tmp/12.txt
1212
[root@localhost ~]#

可以看到文件和内容与脚本中执行的命令一致。

<br />

expect脚本传递参数

expect脚本也是可以像shell脚本一样传递参数的,以下例子演示如何拿到脚本的参数:

[root@localhost ~/expectFiles]# vim telnet_3.expect
#!/usr/bin/expect
# expect脚本拿参数的方式有点像是在数组中拿元素一样,也是从0开始数,$argv是expect的一个内置变量
set user [lindex $argv 0] # 第一个参数
set host [lindex $argv 1]  # 第二个参数
set passwd "123456"
# 需要远程执行的命令
set cm [lindex $argv 2]  # 第三个参数
spawn ssh $user@$host

expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
# 执行命令然后退出登录
expect "]#"
send "$cm\r"
expect "]#"
send "exit\r"

以上脚本运行结果:

[root@localhost ~/expectFiles]# ./telnet_3.expect root 192.168.77.128 ls
spawn ssh root@192.168.77.128
root@192.168.77.128's password: 
Last login: Wed Nov 29 15:10:48 2017 from 192.168.77.130
[root@localhost ~]# ls
\                                           stop.sh     zabbix-release-3.2-1.el7.noarch.rpm
anaconda-ks.cfg                             Test.class
MysqL57-community-release-el7-8.noarch.rpm  Test.java
[root@localhost ~]# 
[root@localhost ~/expectFiles]#

执行多条命令,使用引号将命令括起来即可:

[root@localhost ~/expectFiles]# ./telnet_3.expect root 192.168.77.128 "ls;w;who"
spawn ssh root@192.168.77.128
root@192.168.77.128's password: 
Last login: Wed Nov 29 15:29:30 2017 from 192.168.77.130
[root@localhost ~]# ls;w;who
\                                           stop.sh     zabbix-release-3.2-1.el7.noarch.rpm
anaconda-ks.cfg                             Test.class
MysqL57-community-release-el7-8.noarch.rpm  Test.java
 15:29:48 up  5:13,2 users,load average: 0.00,0.01,0.05
USER     TTY      FROM             LOGIN@   IDLE   Jcpu   Pcpu WHAT
root     pts/0    192.168.77.1     14:07   15:00   0.06s  0.06s -bash
root     pts/1    192.168.77.130   15:29    0.00s  0.02s  0.00s w
root     pts/0        2017-11-29 14:07 (192.168.77.1)
root     pts/1        2017-11-29 15:29 (192.168.77.130)
[root@localhost ~]# [root@localhost ~/expectFiles]#

关于这种远程执行命令的操作,会存在一个超时时间,也就是说,如果你需要远程执行的那条命令的执行时间,超过了默认的超时时间,命令的执行就会被终止。这个默认的超时时间是10秒,我们可以通过执行一条vmstat命令来测试出这个默认的超时时间:

[root@localhost ~/expectFiles]# ./telnet_3.expect root 192.168.77.128 "vmstat 1"
spawn ssh root@192.168.77.128
root@192.168.77.128's password: 
Last login: Wed Nov 29 17:25:48 2017 from 192.168.77.130
[root@localhost ~]# vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 3271556   1376 259272    0    0     4     1   35   64  0  0 100  0  0
 0  0      0 3271712   1376 259364    0    0     0     0   92  157  0  0 100  0  0
 0  0      0 3271712   1376 259364    0    0     0     0   76  128  0  0 100  0  0
 0  0      0 3271744   1376 259364    0    0     0     0   91  146  0  1 100  0  0
 0  0      0 3271744   1376 259364    0    0     0     0   64  120  0  0 100  0  0
 0  0      0 3271712   1376 259364    0    0     0     0   78  127  0  0 100  0  0
 0  0      0 3271712   1376 259364    0    0     0     0   57  104  0  0 100  0  0
 0  0      0 3271712   1376 259364    0    0     0     0   81  128  0  1 100  0  0
 0  0      0 3271712   1376 259364    0    0     0     0   75  127  0  0 100  0  0
 0  0      0 3271200   1376 259400    0    0     0     0   91  153  0  1 100  0  0
 0  0      0 3270936   1376 259400    0    0     0     0   92  152  0  0 100  0  0
[root@localhost ~/expectFiles]#

以上运行结果可以看到vmstat设置的间隔时间为1秒,只打印了11行数据就退出登录了,第一行打印不算在超时时间内,从第二行开始数,刚好是10行,每行打印的间隔时间是1秒,所以就可以知道默认的超时时间是10秒。

那么要如何修改这个默认的超时时间呢?只需要在脚本中加上一句set timeout即可,设置的时间单位为秒,示例:

#!/usr/bin/expect
set user [lindex $argv 0]
set host [lindex $argv 1]
set passwd "Zero-One1."
set cm [lindex $argv 2]
spawn ssh $user@$host
# 设置超时时间为3秒
set timeout 3

expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect "]#"
send "$cm\r"
expect "]#"
send "exit\r"

运行结果:

[root@localhost ~/expectFiles]# ./telnet_3.expect root 192.168.77.128 "vmstat 1"
spawn ssh root@192.168.77.128
root@192.168.77.128's password: 
Last login: Wed Nov 29 17:25:54 2017 from 192.168.77.130
[root@localhost ~]# vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 3271172   1376 259420    0    0     4     1   35   64  0  0 100  0  0
 0  0      0 3270968   1376 259508    0    0     0     0  104  174  0  0 100  0  0
 0  0      0 3270936   1376 259560    0    0     0     0   90  152  0  1 100  0  0
 0  0      0 3270780   1376 259596    0    0     0     0   83  137  0  0 100  0  0
[root@localhost ~/expectFiles]#

提示:如果你将set timeout的值设置为-1的话,就表示没有超时时间,命令会一直执行。

<br />

expect脚本同步文件

expect结合rsync 可以实现自动同步文件,代码示例:

[root@localhost ~/expectFiles]# vim synFile.expect
#!/usr/bin/expect
set passwd "123456"
spawn rsync -av root@192.168.77.128:/tmp/12.txt /tmp/

expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof

以上脚本运行结果:

[root@localhost ~/expectFiles]# chmod a+x synFile.expect
[root@localhost ~/expectFiles]# ./synFile.expect 
spawn rsync -av root@192.168.77.128:/tmp/12.txt /tmp/
root@192.168.77.128's password: 
receiving incremental file list
12.txt

sent 30 bytes  received 84 bytes  228.00 bytes/sec
total size is 5  speedup is 0.04
[root@localhost ~/expectFiles]# cat /tmp/12.txt 
1212
[root@localhost ~/expectFiles]#

如果把脚本中的expect eof命令给注释掉,看看会发生什么:

[root@localhost ~/expectFiles]# ./synFile.expect 
spawn rsync -av root@192.168.77.128:/tmp/12.txt /tmp/
root@192.168.77.128's password: 
[root@localhost ~/expectFiles]#

从结果可以看到,还没来得及执行rsync命令就退出来了,所以在这种登录后需要执行命令的expect脚本中一定要加上expect eof或者interact,不然你需要远程执行的命令就会来不及被执行,这就是加不加expect eof或者interact的区别。

可能有些人会想到使用set timeout来设置一个超时时间避免马上退出登录,实际上是无效的,避免这种马上退出登录的方式只能用expect eof或者interact。

<br />

expect脚本指定host和要同步的文件

想要指定host和要同步的文件就把它们作为参数就好了:

#!/usr/bin/expect
set passwd "123456"
set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -av $file root@$host:$file

expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}

expect eof

运行结果:

[root@localhost ~/expectFiles]# chmod a+x hostFile.expect 
[root@localhost ~/expectFiles]# ./hostFile.expect 192.168.77.128 "/tmp/12.txt"
spawn rsync -av /tmp/12.txt root@192.168.77.128:/tmp/12.txt
root@192.168.77.128's password: 
sending incremental file list

sent 31 bytes  received 12 bytes  86.00 bytes/sec
total size is 5  speedup is 0.12
[root@localhost ~/expectFiles]#

文件的路径要写绝对路径,然后需要使用双引号引起来。

使用expect编写脚本的更多相关文章

  1. Swift设计模式之命令模式

    转自Swift设计模式原文Design-Patterns-In-Swift

  2. openstack学习笔记七 swift安装

    指定映射位置创建ring文件启动服务代维服务proxyserver

  3. openstack安装liberty--安装对象存储服务swift

    通常使用CACHE技術提高性能Accountservers賬戶服務,管理對象存儲中的賬戶定義。Containerservers容器服務,在對象存儲中管理容器或文件夾映……Objectservers對象服務,在存儲節點管理實際的對象,比如文件。Wsgimiddleware處理認證,通常使用OPENSTACKIdentityswiftclient為用戶提供命令行接口使用RESTAPIswift-init初始化和構建RING文件腳本swift-recon一個命令行工具,用於檢索群集的各種度量和測試信息。

  4. Ceph部署二RGW搭建

    背景CephRGW简介CephRGW基于librados,是为应用提供RESTful类型的对象存储接口。环境规划如上篇文章《Ceph部署(一)集群搭建》所述:4台服务器:1台作为Monitor,1台作为OSDRGW,还有两台作为OSD。部署CephRGW进入上文所述的my-cluster目录。该脚本会连接RGW,创建一个bucket并列出所有的bucket。正常的输出应该为:小结通过ceph-deploy命令,已经大大地简化了对Ceph集群和RGW的安装和配置。但如果想挑战下自己,或者想让自己了解更多,试

  5. EFColorPicker - 一个纯 Swift 的轻量级 iOS 颜色选择器

    EFColorPicker是一个纯Swift的轻量级iOS颜色选择器,受MSColorPicker启发。或执行以下命令:环境iOS8.0+Xcode9.0+Swift4.0+安装EFColorPicker可以通过CocoaPods进行获取。只需要在你的Podfile中添加如下代码就能实现引入:备注EFColorPicker的第一个版本从MSColorPicker转换而来,在此对MSColorPicker的作者sgl0v表示感谢!作者EyreFree,eyrefree@eyrefree.org协议EFQRC

  6. 使用LLDB调试Swift

    LLDB是个很好的选择。接下来我会探讨一些工作中常用到的一些LLDB调试技巧。LLDB拥有大量有用的调试工具。LLDB的bugreport命令可以生成一份详细的app当前状态的报告。这些命令有针对C++,Objective-C,Swift和RenderScript的。使用LLDB的这些命令可以让调试变得更自动化。process用于控制要调试的进程,可把LLDB依附到特定target或从target上解绑。processstatus用于打印当前进程及断点处的相关信息:使用如下命令可继续执行:这等同于Xcod

  7. android – 来自adb的’grep’命令的问题

    当我用adb写的时候:我得到错误输出:但如果我将它拆分为两个操作符:它工作正常.如果唯一的方法是将它拆分为两个–首先进入adbshell,然后运行Inquire,有一种方法可以从c#中执行此操作吗?

  8. android – 交互式设置屏幕设置

    我想在KitKat中将屏幕锁定模式设置为None,这样我就可以运行CTS了.我正在使用DragonBoardAPQ8074进行Intrinsyc的开发,他们刚刚发布了针对AndroidKitKat4.4.2的BSP.麻烦的是,它不稳定,设置中的安全菜单崩溃了.所以我不能使用adbshell来输入keyevents19,20,21,22,23进行导航.adbshellsettings命令似乎应该适用

  9. 将我的Android应用程序签名为系统应用程序

    将我的Android应用程序签名为系统应用程序在我的公司,我们希望在现场完全控制电池消耗,仅使用2g和gps可以快速耗尽电池.我们的决定是我们需要拥有移动电话的root权限,这样当手机闲置时,我们就会关掉那些不必要的电池消耗.而且我们也不允许用户将其卸载并清除数据.我的问题是:>我从哪里获得这些签名密钥?>它是否会像root访问权限一样如果我成功地成功了签字?

  10. 获得Android App的“root”权限

    我想知道如何从Android应用程序获得root权限?我尝试了下面的代码行来列出文件但没有发生任何事情我试图在我的清单文件中给予TEST_FACTORY权限,但是我收到错误“允许系统应用”如何制作我的应用系统应用?

随机推荐

  1. 在airgapped(离线)CentOS 6系统上安装yum软件包

    我有一个CentOS6系统,出于安全考虑,它已经被空气泄漏.它可能从未连接到互联网,如果有,它很长时间没有更新.我想将所有.rpm软件包放在一个驱动器上,这样它们就可以脱机安装而无需查询互联网.但是,我在测试VM上遇到的问题是,即使指定了本地路径,yum仍然会挂起并尝试从在线存储库进行更新.另外,有没有办法使用yum-utils/yumdownloader轻松获取该包的所有依赖项和所有依赖项?目前

  2. centos – 命名在日志旋转后停止记录到rsyslog

    CentOS6.2,绑定9.7.3,rsyslog4.6.2我最近设置了一个服务器,我注意到在日志轮换后,named已停止记录到/var/log/messages.我认为这很奇怪,因为所有日志记录都是通过rsyslog进行的,并且named不会直接写入日志文件.这更奇怪,因为我在更新区域文件后命名了HUPed,但它仍然没有记录.在我停止并重新启动命名后,记录恢复.这里发生了什么?

  3. centos – 显示错误的磁盘大小

    对于其中一个磁盘,Df-h在我的服务器上显示错误的空白区域:Cpanel表明它只有34GB免费,但还有更多.几分钟前,我删除了超过80GB的日志文件.所以,我确信它完全错了.fdisk-l/dev/sda2也显示错误:如果没有格式化,我该怎么做才能解决这个问题?并且打开文件描述符就是它需要使用才能做到这一点.所以…使用“lsof”并查找已删除的文件.重新启动写入日志文件的服务,你很可能会看到空间可用.

  4. 如何在centos 6.9上安装docker-ce 17?

    我目前正在尝试在centOS6.9服务器上安装docker-ce17,但是,当运行yuminstalldocker-ce时,我收到以下错误:如果我用跳过的标志运行它我仍然得到相同的消息,有没有人知道这方面的方法?

  5. centos – 闲置工作站的异常负载平均值

    我有一个新的工作站,具有不寻常的高负载平均值.机器规格是:>至强cpu>256GB的RAM>4x512GBSSD连接到LSI2108RAID控制器我从livecd安装了CentOS6.564位,配置了分区,网络,用户/组,并安装了一些软件,如开发工具和MATLAB.在启动几分钟后,工作站负载平均值的值介于0.5到0.9之间.但它没有做任何事情.因此我无法理解为什么负载平均值如此之高.你能帮我诊断一下这个问题吗?

  6. centos – Cryptsetup luks – 检查内核是否支持aes-xts-plain64密码

    我在CentOS5上使用cryptsetupluks加密加密了一堆硬盘.一切都很好,直到我将系统升级到CentOS6.现在我再也无法安装磁盘了.使用我的关键短语装载:我收到此错误:在/var/log/messages中:有关如何装载的任何想法?找到解决方案问题是驱动器使用大约512个字符长的交互式关键短语加密.出于某种原因,CentOS6中的新内核模块在由旧版本创建时无法正确读取512个字符的加密密钥.似乎只会影响内核或cryptsetup的不同版本,因为在同一系统上创建和打开时,512字符的密钥将起作用

  7. centos – 大量ssh登录尝试

    22个我今天登录CentOS盒找到以下内容这是过去3天内的11次登录尝试.WTF?请注意,这是我从我的提供商处获得的全新IP,该盒子是全新的.我还没有发布任何关于此框的内容.为什么我会进行如此大量的登录尝试?是某种IP/端口扫描?基本上有4名匪徒,其中2名来自中国,1名来自香港,1名来自Verizon.这只发生在SSH上.HTTP上没有问题.我应该将罪魁祸首子网路由吗?你们有什么建议?

  8. centos – kswap使用100%的CPU,即使有100GB的RAM也可用

    >Linux内核是否应该足够智能,只需从内存中清除旧缓存页而不是启动kswap?

  9. centos – Azure将VM从A2 / 3调整为DS2 v2

    我正在尝试调整前一段时间创建的几个AzureVM,从基本的A3和标准A3到标准的DS2v2.我似乎没有能力调整到这个大小的VM.必须从头开始重建服务器会有点痛苦.如果它有所不同我在VM中运行CentOS,每个都有一个带有应用程序和操作系统的磁盘.任何人都可以告诉我是否可以在不删除磁盘的情况下删除VM,创建新VM然后将磁盘附加到新VM?

  10. centos – 广泛使用RAM时服务器计算速度减慢

    我在非常具体的情况下遇到服务器速度下降的问题.事实是:>1)我使用计算应用WRF>2)我使用双XeonE5-2620v3和128GBRAM(NUMA架构–可能与问题有关!

返回
顶部