zoukankan      html  css  js  c++  java
  • 关于expect的实战总结

    如何从机器A上ssh到机器B上,然后执行机器B上的命令?如何使之自动化完成?看完下面的文章你就明白了 

    一、安装

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

    sudo apt-get install tcl tk expect

    或者

    yum install -y tcl tclx tcl-devel

    二、如何使用

    expect是linux中的一个用来处理交互的命令。借助Expect,我们可以将交互过程写在一个脚本上,使之自动化完成。形象的说,ssh登录,ftp登录等都符合交互的定义。下文我们首先提出一个问题,然后介绍基础知四个命令

    四个命令

    Expect中最关键的四个命令是send,expect,spawn,interact。

    send:用于向进程发送字符串
    expect:从进程接收字符串
    spawn:启动新的进程
    interact:允许用户交互
    

    1、send

    send命令接收一个字符串参数,并将该参数发送到进程。

    expect1.1> send "hello world\n"
    hello world
    

    2. expect命令

    启用选项

    • -c:执行脚本前先执行的命令,可多次使用。

    • -d:debug模式,可以在运行时输出一些诊断信息,与在脚本开始处使用exp_internal 1相似。

    • -D:启用交换调式器,可设一整数参数。

    • -f:从文件读取命令,仅用于使用#!时。如果文件名为"-",则从stdin读取(使用"./-"从文件名为-的文件读取)。

    • -i:交互式输入命令,使用"exit"或"EOF"退出输入状态。

    • --:标示选项结束(如果你需要传递与expect选项相似的参数给脚本时),可放到#!行:#!/usr/bin/expect --

    • -v:显示expect版本信息。

    expect命令和send命令正好相反,expect通常是用来等待一个进程的反馈。expect可以接收一个字符串参数,也可以接收正则表达式

    expect "hi\n"
    send "hello there!\n"

    这两行代码的意思是:从标准输入中等到hi和换行键后,向标准输出输出hello there。

    看一段代码:

    #!/usr/bin/expect -f
    expect "hi
    "
    send "you typed <$expect_out(buffer)>"
    send "but I only expected <$expect_out(0,string)>"
    

    执行结果

    1
    2
    3
    4
    5
    hi
    you typed <1
    2
    3
    4
    5
    hi
    >but I only expected <hi
    

    多分支模式

    expect "hi" { send "You said hi\n" } \
    "hello" { send "Hello yourself\n" } \
    "bye" { send "That was unexpected\n
    

    或者下面的写法

    expect {
    "hi" { send "You said hi\n"}
    "hello" { send "Hello yourself\n"}
    "bye" { send "That was unexpected\n"}
    }

    3、spawn

    spawn命令就是用来启动新的进程的,比如登录ftp

    spawn ftp ftp.test.com
    

    4、interact

    interact ##是Expect用来打开用户与产生进程之间通信的命令,简单说就是登陆以后将远程服务器的终端保持在当前终端,而不是将远程终端关掉

    #!/usr/bin/expect -f
    set timeout -1  
    spawn ssh $user@$host
    expect -exact  "password" 
    send "$password
    "
    send --  "pwd
    "
    interacter

    三、总结

    1、常用命令

    # 命令行参数 
    # $argv,参数数组,使用[lindex $argv n]获取,$argv 0为脚本名字
    # $argc,参数个数
    set username [lindex $argv 1]  # 获取第1个参数
    set passwd [lindex $argv 2]    # 获取第2个参数
     
    set timeout 30 # 设置超时
     
    # spawn是expect内部命令,开启ssh连接
    spawn ssh -l username 192.168.1.1
     
    # 判断上次输出结果里是否包含“password:”的字符串,如果有则立即返回,否则就等待一段时间(timeout)后返回
    expect "password:"
     
    # 发送内容ispass(密码、命令等)
    send "ispass
    "
     
    # 发送内容给用户
    send_user "$argv0 [lrange $argv 0 2]
    "
    send_user "It's OK
    "
    # 执行完成后保持交互状态,控制权交给控制台(手工操作)。否则会完成后会退出。
    interact

    2、命令介绍

    • close:关闭当前进程的连接。
    • debug:控制调试器。
    • disconnect:断开进程连接(进程仍在后台运行)。
    • 执行priv_prog:定时读取密码
    • exit:退出expect。
    • exp_continue [-continue_timer]:继续执行下面的匹配。
    • exp_internal [-f file] value:
    send_user "password? "
    expect_user -re "(.*)
    "
    for {} 1 {} {
        if {[fork]!=0} {sleep 3600;continue}
        disconnect
        spawn priv_prog
        expect Password:
        send "$expect_out(1,string)
    "
        . . .
        exit
    }

    3、范例

    A、自动telnet会话

    #!/usr/bin/expect -f
    set ip [lindex $argv 0 ]         # 接收第1个参数,作为IP
    set userid [lindex $argv 1 ]     # 接收第2个参数,作为userid
    set mypassword [lindex $argv 2 ] # 接收第3个参数,作为密码
    set mycommand [lindex $argv 3 ]  # 接收第4个参数,作为命令
    set timeout 10                   # 设置超时时间
     
    # 向远程服务器请求打开一个telnet会话,并等待服务器询问用户名
    spawn telnet $ip
        expect "username:"
        # 输入用户名,并等待服务器询问密码
        send "$userid
    "
        expect "password:"
        # 输入密码,并等待键入需要运行的命令
        send "$mypassword
    "
        expect "%"
        # 输入预先定好的密码,等待运行结果
        send "$mycommand
    "
        expect "%"
        # 将运行结果存入到变量中,显示出来或者写到磁盘中
        set results $expect_out(buffer)
        # 退出telnet会话,等待服务器的退出提示EOF
        send "exit
    "
        expect eof

    B、自动建立FTP会话

    #!/usr/bin/expect -f
    setip [lindex $argv 0 ]         # 接收第1个参数,作为IP
    setuserid [lindex $argv 1 ]     # 接收第2个参数,作为Userid
    setmypassword [lindex $argv 2 ] # 接收第3个参数,作为密码
    settimeout 10                   # 设置超时时间
    # 向远程服务器请求打开一个FTP会话,并等待服务器询问用户名
    spawn ftp$ip
        expect "username:"
        # 输入用户名,并等待服务器询问密码
        send "$userid
    "
        expect "password:"
        # 输入密码,并等待FTP提示符的出现
        send "$mypassword
    "
        expect "ftp>"
        # 切换到二进制模式,并等待FTP提示符的出现
        send "bin
    "
        expect "ftp>"
        # 关闭ftp的提示符
        send "prompt
    "
        expect "ftp>"
        # 下载所有文件
        send "mget *
    "
        expect "ftp>"
        # 退出此次ftp会话,并等待服务器的退出提示EOF
        send "bye
    "
        expect eof

    C、自动登录ssh执行命令

    #!/usr/bin/expect
    set IP     [lindex $argv 0]
    set USER   [lindex $argv 1]
    set PASSWD [lindex $argv 2]
    set CMD    [lindex $argv 3]
     
    spawn ssh $USER@$IP $CMD
    expect {
        "(yes/no)?" {
            send "yes
    "
            expect "password:"
            send "$PASSWD
    "
            }
        "password:" {send "$PASSWD
    "}
        "* to host" {exit 1}
        }
    expect eof

    D、批量登录ssh服务器执行操作范例,设定增量的for循环

    #!/usr/bin/expect
    for {set i 10} {$i <= 12} {incr i} {
        set timeout 30
        set ssh_user [lindex $argv 0]
        spawn ssh -i .ssh/$ssh_user abc$i.com
     
        expect_before "no)?" {
        send "yes
    " }
        sleep 1
        expect "password*"
        send "hello
    "
        expect "*#"
        send "echo hello expect! > /tmp/expect.txt
    "
        expect "*#"
        send "echo
    "
    }
    exit

    E、批量登录ssh并执行命令,foreach语法

    #!/usr/bin/expect
    if {$argc!=2} {
        send_user "usage: ./expect ssh_user password
    "
        exit
    }
    foreach i {11 12} {
        set timeout 30
        set ssh_user [lindex $argv 0]
        set password [lindex $argv 1]
        spawn ssh -i .ssh/$ssh_user root@xxx.yy.com
        expect_before "no)?" {
        send "yes
    " }
        sleep 1
     
        expect "Enter passphrase for key*"
        send "password
    "
        expect "*#"
        send "echo hello expect! > /tmp/expect.txt
    "
        expect "*#"
        send "echo
    "
    }
    exit 

    F、从命令行获取服务器IP,foreach语法,expect嵌套

    #!/usr/bin/expect
    # 使用方法: script_name ip1 ip2 ip3 ...
     
    set timeout 20
    if {$argc < 1} {
      puts "Usage: script IPs"
      exit 1
    }
    # 替换你自己的用户名
    set user "username"
    #替换你自己的登录密码
    set password "yourpassword"
     
    foreach IP $argv {
    spawn ssh $user@$IP
     
    expect 
      "(yes/no)?" {
        send "yes
    "
        expect "password:?" {
          send "$password
    "
        }
      } "password:?" {
        send "$password
    "
    }
     
    expect "$?"
    # 替换你要执行的命令
    send "last
    "
    expect "$?"
    sleep 10
    send "exit
    "
    expect eof
    }

    G、ssh自动登录expect脚本

    #!/usr/bin/expect -f
    # Auther:YuanXing
    # Update:2014-02-08
    if {$argc < 4} {
        send_user "Usage:
      $argv0 IPaddr User Passwd Port Passphrase
    "
        puts stderr "argv error!
    "
        sleep 1
        exit 1
    }
     
    set ip         [lindex $argv 0 ]
    set user       [lindex $argv 1 ]
    set passwd     [lindex $argv 2 ]
    set port       [lindex $argv 3 ]
    set passphrase [lindex $argv 4 ]
    set timeout 6
    if {$port == ""} {
        set port 22
    }
    #send_user "IP:$ip,User:$user,Passwd:$passwd,Port:$port,Passphrase:$passphrase"
    spawn ssh -p $port $user@$ip
     
    expect_before "(yes/no)\?" {
        send "yes
    "}
     
    expect 
    "Enter passphrase for key*" {
        send "$passphrase
    "
        exp_continue
    } " password:?" {
        send "$passwd
    "
        exp_continue
    } "*[#\$]" {
        interact
    } "* to host" {
        send_user "Connect faild!"
        exit 2
    } timeout {
        send_user "Connect timeout!"
        exit 2
    } eof {
        send_user "Lost connect!"
        exit
    }

    H、通过shell脚本调用

    #!/bin/bash
    
    TMP=$(mktemp)
    username=(test)
    # create expect script
    
    for ip in `cat ip.txt`; do
    
    cat > $TMP << EOF
    set timeout 5
    spawn  ssh  -i  $username/id_rsa   -p888   $username@$ip
    
    expect -exact "$username"  
    send --  "su - 
    "
    
    expect -exact "Password"  
    send --  "213f214##!ds(*&a@
    "
    
    expect -exact "root"  
    send --  "userdel -r zhangshan
    "
    send --  "userdel -r lisi
    "
    
    
    send --  "history -c 
     exit
    "
    send --  "history -c 
     exit
    "
    expect eof
    
    EOF
    
    expect -f $TMP
    rm $TMP
    done
    

      

    参考:

    https://www.cnblogs.com/iloveyoucc/archive/2012/05/11/2496433.html

    http://www.xuetimes.com/archives/781

  • 相关阅读:
    [转]relative、absolute和float
    CSS 布局属性(display,float,clear,visibility,overflow,overflow-x,overflow-y)
    CSS 块状元素和内联元素
    CSS定位
    CSS实例
    jQuery简单实例
    [转]几种常见SQL分页方式
    MyBatis Mapper XML 文件
    MyBatis XML 映射配置文件
    MyBatis 入门
  • 原文地址:https://www.cnblogs.com/chenpingzhao/p/9445190.html
Copyright © 2011-2022 走看看