Expect是由 Don Libes 基于Tcl语言开发的,并被普遍应用于交互式操做和自动化测试的场景中,它尤为适用于须要对多台服务器执行相同操做的环境中,能够大幅度提升系统管理人员的工做效率。目前,大部分 Unix/Linux 系统安装有expect。万一系统中没有,能够从 http://expect.nist.gov/| f52496c84460745c17c9a9c5df59acb61 | 下载相应的包安装。linux
Expect做为基于Tcl的高级语言,增长了一些特殊的语法。传统意义上的Expect是以Tcl扩展包的形式出现的,任何Tcl语言编写的应用程序均可以加载Expect功能;此外,Expect已经以模块的方式移植到了Perl和Python语言中,所以用户一样能够在Perl和Python脚本中利用Expect强大的交互功能。正则表达式
send 、 expect 和 spawn 是Expect语言最基本的命令。
send命令会发送字符床给指定进程(process)。
expect命令会等待接受该进程返回的结果而且会根据返回的字符串来决定下一步的操做。
spawn命令能够发起一个进程的运行。
进入expect环境后才能够执行的expect内部命令bash
$ expect expect1.1> send .... expect1.1> expect .... ........
send命令接收一个字符串做为参数并发送给指定的进程从send "hello world"
这行代码中,send会送出字符串 hello world
。若是expec早已经开始与某一个程序进行交互,那么这个字符串将被发送给该程序;而在一般状况下,这个字符串会被送到标准输出设备。服务器
expect命令则等待一个响应,一般是来自于expect正在与之交互的进程,或者来自于标准输入设备;它会等待一个指定的字符串或者知足给定的正则表达式的任何字符串。咱们能够建立一个名为response.expect
的文件,来看expect是如何处理的,其内容以下:并发
#!expect -f expect "hi" send "hello there"
终端中运行 $ expect response.expect
,它会等待来自标准输入设备的响应,知道用户输入hi
并回车,它才会发送 hello there
到标准输出设备,并回车。而后结束expect脚本的运行。可是若是用户没有输入hi
并回车,那么expect会继续等待hi
;输入其余的字符并不会影响到expect的工做。一般状况下,expect会一直等待输入,直到最终超时退出。此外,expect还支持使用正则表达式来预防expect匹配到未预想到的输入数据。ssh
spawn命令会调用另外一个程序。它的第一个参数要启动程序的名字;剩余的参数则会被传递给该程序做为参数。好比:测试
expect1.1> spawn ssh username@192.168.1.1
命令会衍生出一个ssh进程,以username用户的身份登录ip地址为192.168.1.1的电脑中。spa
用户经过spawn,send和expect这三个基本命令,就能够编写一段expect程序来实现自动化工做。code
$ sudo emerge -avt dev-tcltk/expect
当你想经过lftp登录别人的电脑同步文件时,若只执行lftp sftp:://user@x.x.x.x
登录了别人的电脑,你会发现其实这只是一种假象,实际上你并无成功登录别人的电脑,因此你需先执行ssh user@x.x.x.x
而后在执行上述命令,便可登录成功。这样作的话,你须要屡次输入ip、用户名、密码,很费时间。为了可以提升效率,能够借助expect脚本。过程以下:建立一个ssh.expect的脚本,分别说一下执行脚本时有参数的脚本内容和无参数的脚本内容。进程
有参数的脚本内容以下:
#!/usr/bin/expect set timeout 1 set host [lindex $argv 0] set user [lindex $argv 1] set password [lindex $argv 2] spawn ssh $host -l $user expect { "(yes/no)?" { send "yes" expect "Password" send "$password\r" } "Password:" { send "$password\r" } } send "exit \n" spawn lftp sftp://$user@$host expect "Password:" send "$password\r" interact
假如你想以xiaomi
的用户名登录ip
为192.168.0.50
登录密码为123
的电脑,则在终端执行$ expect ssh.expect 192.168.0.50 xiaomi 123
,终端显示lftp xiaomi@192.168.0.50:~>
。
无参数的脚本内容以下:
#!/usr/bin/expect set timeout 1 set host 192.168.0.50 set user xiaomi set password 123 spawn ssh $host -l $user expect { "(yes/no)?" { send "yes" expect "Password" send "$password" } "Password:" { send "$password\r" } } send "exit \n" spawn lftp sftp://$user@$host expect "Password:" send "$password\r" interact
在终端执行$ expect ssh.expect
,终端显示lftp xiaomi@192.168.0.50:~>
。
其中timeout
为send将信息发送给标准输入设备等待执行的时间,你能够修改一下变量值,观察如下效果。
注意send “123\r”
中的123
为你的sudo密码。
#!/usr/bin/expect set timeout 60 set kernel [lindex $argv 0] spawn su expect "Password:" send "123\r" expect "#" send "cd /usr/src/ \n" expect "#" send "cp ./linux/.config ./linux-$kernel-gentoo/ \n" expect "#" send "rm linux \n" expect "#" send "ln -s /usr/src/linux-$kernel-gentoo linux \n" expect "#" send "cd linux \n" expect "#" send "make -j4 && make modules_install \n" expect "#" send "mount /boot && rm /boot/kernel-* \n" expect "#" send "cp arch/x86/boot/bzImage /boot/kernel-$kernel-gentoo \n" expect "#" send "grub2-mkconfig -o /boot/grub/grub.cfg \n" expect "#" send "grub2-install /dev/sda \n" expect "#" send "exit \n" interact
$ expect kernel_renew.expect 4.2.1//4.2.1为你内核新版本号