首页 > 其他分享 >(转)expect学习笔记及实例详解

(转)expect学习笔记及实例详解

时间:2022-12-18 20:34:59浏览次数:67  
标签:spawn set eof 实例 send 详解 expect user


expect学习笔记及实例详解



1. expect 是基于tcl 演变而来的,所以很多语法和tcl 类似,基本的语法如下



所示:



1.1 首行加上/usr/bin/expect



1.2 spawn: 后面加上需要执行的shell 命令,比如说spawn sudo touch testfile



1.3 expect: 只有spawn 执行的命令结果才会被expect 捕捉到,因为spawn 会启



动一个进程,只有这个进程的相关信息才会被捕捉到,主要包括:标准输入的提



示信息,eof 和timeout。



1.4 send 和send_user:send 会将expect 脚本中需要的信息发送给spawn 启动



的那个进程,而send_user 只是回显用户发出的信息,类似于shell 中的echo 而



已。



 



2. 一个小例子,用于linux 下账户的建立:



filename: account.sh,可以使用./account.sh newaccout 来执行;



1 #!/usr/bin/expect



2



3 set passwd "mypasswd"



4 set timeout 60



5



6 if {$argc != 1} {



7 send "usage ./account.sh \$newaccount\n"



8 exit



9 }



10



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



12



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



14



15 expect {



16 "assword" {



17 send_user "sudo now\n"



18 send "$passwd\n"



19 exp_continue



20 }



21 eof



22 {



23 send_user "eof\n"



24 }



25 }



26



27 spawn sudo passwd $user



28 expect {



29 "assword" {



30 send "$passwd\n"



31 exp_continue



32 }



33 eof



34 {



35 send_user "eof"



36 }



37 }



38



39 spawn sudo smbpasswd -a $user



40 expect {



41 "assword" {



42 send "$passwd\n"



43 exp_continue



44 }



45 eof



46 {



47 send_user "eof"



48 }



49 }



 



3. 注意点:



 



第3 行: 对变量赋值的方法;



第4 行: 默认情况下,timeout 是10 秒;



第6 行: 参数的数目可以用$argc 得到;



第11 行:参数存在$argv 当中,比如取第一个参数就是[lindex $argv 0];并且



如果需要计算的话必须用expr,如计算2-1,则必须用[expr 2-1];



第13 行:用spawn 来执行一条shell 命令,shell 命令根据具体情况可自行调整;



有文章说sudo 要加-S,经过实际测试,无需加-S 亦可;



第15 行:一般情况下,如果连续做两个expect,那么实际上是串行执行的,用。 expect 与“{ ”之间直接必须有空格或则TAB间隔,否则会出麻烦,会报错 invalid command name "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 下一个命令,但是不



要依赖这种行为,很有可能今天还可以,明天就不能用了;



 



4. 其他



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



1 #!/usr/bin/expect



2



3 set timeout 30



4 spawn ssh 10.192.224.224



5 expect "password:"



6 send "mypassword\n"



7 expect "*$"



send "mkdir tmpdir\n" #远程执行命令用send发送,不用spawn



9 expect "*$" #注意这个地方,要与操作系统上环境变量PS1相匹配,尤其是有PS1有空格的情况下,一定在expct "*$ "把空格加上,加不上你就完蛋了。我试过。



这个例子实际上是通过ssh 去登录远程机器,并且在远程机器上创佳一个目录,



我们看到在我们输入密码后并没有去expect eof,这是因为ssh 这个spawn 并没



有结束,而且手动操作时ssh 实际上也不会自己结束除非你exit;所以你只能



expect bash 的提示符,当然也可以是机器名等,这样才可以在远程创建一个目



录。



注意,请不要用spawn mkdir tmpdir, 这样会使得上一个spawn 即ssh 结束,那



么你的tmpdir 将在本机建立。



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



多赘述。



 



5. 觉得bash 很多情况下已经很强大,所以可能用expect 只需要掌握这些就好了,



其他的如果用到可以再去google 了。



 



源代码图片:



​​



 



​​



 



 



 



​​



 



6 \实例:下面这个脚本是完成对单个服务器scp任务。



1: #!/usr/bin/expect



2:



3: set timeout 10



4: set host [lindex $argv 0]



5: set username [lindex $argv 1]



6: set password [lindex $argv 2]



7: set src_file [lindex $argv 3]



8: set dest_file [lindex $argv 4]



9:



10: spawn scp $src_file $username@$host:$dest_file



11: expect {



12: "(yes/no)?"



13: {



14: send "yes\n"



15: expect "*assword:" { send "$password\n"}



16: }



17: "*assword:"



18: {



19: send "$password\n"



20: }



21: }



22: expect "100%"



23: expect eof



参考源代码图片:






​​

注意代码刚开始的第一行,指定了expect的路径,与shell脚本相同,这一句指定了程序在执行时到哪里去寻找相应的启动程序。代码刚开始还设定了timeout的时间为10秒,如果在执行scp任务时遇到了代码中没有指定的异常,则在等待10秒后该脚本的执行会自动终止。

spawn代表在本地终端执行的语句,在该语句开始执行后,expect开始捕获终端的输出信息,然后做出对应的操作。expect代码中的捕获的(yes/no)内容用于完成第一次访问目标主机时保存密钥的操作。有了这一句,scp的任务减少了中断的情况。代码结尾的expect eof与spawn对应,表示捕获终端输出信息的终止。

 

有了这段expect的代码,还只能完成对单个远程主机的scp任务。如果需要实现批量scp的任务,则需要再写一个shell脚本来调用这个expect脚本。

1: #!/bin/sh



2:



3: list_file=$1



4: src_file=$2



5: dest_file=$3



6:



7: cat $list_file | while read line



8: do



9: host_ip=`echo $line | awk '{print $1}'`



10: username=`echo $line | awk '{print $2}'`



11: password=`echo $line | awk '{print $3}'`



12: echo "$host_ip"



13: ./expect_scp $host_ip $username $password $src_file $dest_file



15: done




参考代码图片如下:






​​

​​

​​

很简单的代码,指定了3个参数:列表文件的位置、本地源文件路径、远程主机目标文件路径。需要说明的是其中的列表文件指定了远程主机ip、用户名、密码,这些信息需要写成以下的格式:

IP username password

中间用空格或tab键来分隔,多台主机的信息需要写多行内容。

这样就指定了两台远程主机的信息。注意,如果远程主机密码中有“$”、“#”这类特殊字符的话,在编写列表文件时就需要在这些特殊字符前加上转义字符,否则expect在执行时会输入错误的密码。

对于这个shell脚本,保存为batch_scp.sh文件,与刚才保存的expect_scp文件和列表文件(就定义为hosts.list文件吧)放到同一目录下执行时按照以下方式输入命令就可以了:

标签:spawn,set,eof,实例,send,详解,expect,user
From: https://blog.51cto.com/u_15740686/5951109

相关文章

  • PendingIntent 详解
    publicfinalclassPendingIntentextendsObjectimplementsParcelable简介PendingIntent用于描述Intent及其最终的行为. 你可以通过......
  • Git应用开发详解之Git入门指引
    Git简史官方网站:https://git-scm.com/​​Linux内核一开始使用BitKeeper来管理和维护代码。2005年,BitKeeper不再免费使用,Linux开源社区需要一套自己的版本控......
  • Git应用开发详解之Git入门指引
    Git简史官方网站:https://git-scm.com/​​Linux内核一开始使用BitKeeper来管理和维护代码。2005年,BitKeeper不再免费使用,Linux开源社区需要一套自己的版本控......
  • Git应用开发详解之Git入门指引
    Git简史官方网站:https://git-scm.com/​​Linux内核一开始使用BitKeeper来管理和维护代码。2005年,BitKeeper不再免费使用,Linux开源社区需要一套自己的版本控......
  • Git应用开发详解之Git入门指引
    Git简史官方网站:https://git-scm.com/​​Linux内核一开始使用BitKeeper来管理和维护代码。2005年,BitKeeper不再免费使用,Linux开源社区需要一套自己的版本控......
  • C#二分查找算法实例分析
    原文链接:https://www.jb51.net/article/65006.htminternalclassProgram{staticvoidMain(string[]args){Programprogram=newProgram();......
  • WebApi 接口参数不再困惑:传参详解
    从网上看了WEBAPI理解感觉是不错的分享一下前言:还记得刚使用WebApi那会儿,被它的传参机制折腾了好久,查阅了半天资料。如今,使用WebApi也有段时间了,今天就记录下API接口传参......
  • 13 刘欣晨 第八章实例+实战
    实验 一 项目名称:    创建计算BMI指数的模块 deffun_bmi(person,height,weight):'''功能:根据身高体重计算BMI指数person:姓名height:身高,......
  • matplotlib绘图详解
    目录matplotlib绘图详解一、基础准备1、matplotlib简介2、环境准备2.1安装2.2参考文档3、图表结构4、常用图表二、绘图步骤1、常用图表1.1散点图1.2柱状图1.3饼......
  • MyBatis核心配置文件详解
    目录environmentstransactionManagerDataSource引入jdbc.propertiestypeAliasessettings下划线转驼峰延迟加载MappersIDEA核心配置模板及解释environments可以配置多个......