zoukankan      html  css  js  c++  java
  • 转expect 文一篇。

    用expect实现通过scp自动上传文件的脚本

      最近在公司写了一个scp自动向远程主机传文件的脚本。由于scp使用交互式的方式获取密码,因此要实现脚本的自动登陆有两种方法,一种是配置信任,但是貌似,就目前我所了解到的,配置信任无法限制权限问题,一旦配置了ssh的信任,则对方可以通过ssh、sftp等各种方式登陆主机。。。。
        所以使用第二种方法,expect。
        expect是基于tcl的一种脚本语言,它主要是为了实现交互式的脚本(貌似perl也可以做到,但是我不会-_-)。
        expect并不在linux的默认安装包里,因此需要独自安装。源码很好找。另外,expect的安装需要tcl的源码。。

    Tcl安装方法:下载tcl包。(建议8.4.13,因脚本己在8.4.13下测试通过。下同),解压后进入源码根文件夹,执行以下命令

             Cd unix

             ./configure --prefix=/usr/tcl

             Make

             Make install

             Cd ..

             cp ./unix/tclUnixPort.h ./generic/

             

        不要删除源码。安装expect需要用到

     

    然后解压expect包,(建议5.43.0)进入expect源码根文件夹

    ./configure -prefix=/usr/expect -with-tcl=/usr/tcl/lib -with-x=no -with-tclinclude=/root/tcl8.4.13/generic

    加粗斜体部分为你的tcl源码包的文件夹

    然后

             Make

             Make install


     

        这样expect就安装好了,自动传文件的脚本在最后(-_-刚刚用cublog,不知道怎么在代码后面写正文,所以直接把代码放最后了)

       

       set remotedir [lindex $argv 0]

       这是expect声明变量的方法,中括号内表示的是输入的第一个参数,expect与其它脚本稍有不同,它的第一个参数是argv0,而其他脚本一般为argv1


     

        set timeout 10000000000

       这句是设置超时时间。应该是秒,但是好像不大准确的样子。默认的timeout是10,我设成这么大是因为传送的文件比较多,估计10秒内传不完


     

       if {$file == 0} { if {$load == 0} {spawn scp $mydir $remotedir} else {spawn scp $remotedir $mydir } }

       这就是expect中恶心的if-else语句了。。。这个东西写了我很久,它的条件判断需要放在大括号内,大括号不能独成一行(可以理解,没有";"嘛),另外,else貌似也不能独成一行,必须接到前一个if的后面。而且与大括号之间要有间隔-_-。。具体没搞懂,不过直接写在一行内肯定不会错。


     

       expect "Are you sure you want to continue connecting (yes/no)?" { send "yes\r" } "Password:" { send "$password\r" }"Permission denied*" { break } "*No route to host" { break } "*No such file or directory" { break } timeout { break } eof {break }

       这句就是整个脚本最关键的了。expect后面跟了很多字符串,如果得到了与某个字符串相匹配的串,那么执行该字符串后面的语句。比如得到了"Password:",那就执行send "$password\r"。这里也不能分行写。我从网上找的教程有一个分行写。。害死我了

       另外,求高人指点如果用expect spawn一个没有输出的程序?比如

         ls -l > log.txt

    #!/usr/expect/bin/expect -f

    #usage: scp.exp remotedir mydir password load file
    #argument: load , 0 for upload, 1 for download
    #     file , 0 for single file , 1 for directory

    set remotedir [lindex $argv 0]
    set mydir [lindex $argv 1]
    set password [lindex $argv 2]
    set load [lindex $argv 3]
    set file [lindex $argv 4]
    set timeout 10000000000
    if {$file == 0} { if {$load == 0} {spawn scp $mydir $remotedir} else{spawn scp $remotedir $mydir } }
    if {$file == 1} { if {$load ==0 } {spawn scp -r $mydir $remotedir } else{spawn scp -r $remotedir $mydir } }
    for {} {1} {} { expect "Are you sure you want to continue connecting (yes/no)?" { send "yes\r" } "Password:" { send "$password\r" }"Permission denied*" { break } "*No route to host" { break } "*No such file or directory" { break } timeout { break } eof { break } }
    expect eof


        PS:有一个问题需要注意一下,如果在expect中
          spawn ls /*
        会出错,提示找不到/*这个文件,看起来expect是把*解释成了普通字符而非正则表达式。
  • 相关阅读:
    solaris10 服务管理
    DLL的导出导入与调用
    c# Font字体
    WaitForMultipleObjects、WaitForSingleObject、GetExitCodeThread
    solaris10补丁管理
    注册表API函数
    简单的编码加密
    asp.net 调用外部程序
    Global.cs 获取网址
    Jquery easyui dialog组件, 默认不自动打开
  • 原文地址:https://www.cnblogs.com/dracula/p/1913797.html
Copyright © 2011-2022 走看看