Mac 自动化执行脚本 Expect

环境

Mac

安装expect

brew install expect

使用

传参

# 表示获取执行脚本命名空格后第一个参数
set user [lindex $argv 0]

实际应用例子

ssh自动登录

#!/usr/bin/expect
set user root  
set ipaddress 120.76.xx.xx
set passwd xxx
set timeout 30

spawn ssh $user@$ipaddress
expect {
    "*password:" { send "$passwd\r" }
    "yes/no" { send "yes\r";exp_continue }
}
interact

#!/usr/bin/expect -f
spawn ssh -p 22 developer@120.76.103.192 
expect "*password:"
send "Sound318\r"
interact #操作完成

scp传输例子

#!/usr/bin/expect 
set user root  
set user host  
set pwd 123pwd
set from_path 120.76.xx.xx
set to_path xxx

spawn scp $from_path $user@$host:$to_path
expect {
    "*password:" { send "$pwd\n" }
}
interact

录制脚本

可以使用提供的脚本进行录制

vim autoexpect.exp

#!/usr/bin/expect --
# Name: autoexpect - generate an Expect script from watching a session
#
# Description:
#
# Given a program name, autoexpect will run that program.  Otherwise
# autoexpect will start a shell.  Interact as desired.  When done, exit
# the program or shell.  Autoexpect will create a script that reproduces
# your interactions.  By default, the script is named script.exp.
# See the man page for more info.
#
# Author: Don Libes, NIST
# Date: June 30 1995
# Version: 1.4b

set filename "script.exp"
set verbose 1
set conservative 0
set promptmode 0
set option_keys ""

proc check_for_following {type} {
    if ![llength [uplevel set argv]] {
        puts "autoexpect: [uplevel set flag] requires following $type"
        exit 1
    }
}    

while {[llength $argv]>0} {
    set flag [lindex $argv 0]
    if 0==[regexp "^-" $flag] break
    set argv [lrange $argv 1 end]
    switch -- $flag \
      "-c" {
        set conservative 1
    } "-C" {
        check_for_following character
        lappend option_keys [lindex $argv 0] ctoggle
        set argv [lrange $argv 1 end]
    } "-p" {
        set promptmode 1
    } "-P" {
        check_for_following character
        lappend option_keys [lindex $argv 0] ptoggle
        set argv [lrange $argv 1 end]
    } "-Q" {
        check_for_following character
        lappend option_keys [lindex $argv 0] quote
        set argv [lrange $argv 1 end]
    } "-f" {
        check_for_following filename
        set filename [lindex $argv 0]
        set argv [lrange $argv 1 end]
    } "-quiet" {
        set verbose 0
    } default {
        break
    }
}

#############################################################
# Variables    Descriptions
#############################################################
# userbuf    buffered characters from user
# procbuf    buffered characters from process
# lastkey    last key pressed by user
#        if undefined, last key came from process
# echoing    if the process is echoing
#############################################################

# Handle a character that came from user input (i.e., the keyboard)
proc input {c} {
    global userbuf lastkey

    send -- $c
    append userbuf $lastkey
    set lastkey $c
}

# Handle a null character from the keyboard
proc input_null {} {
    global lastkey userbuf procbuf echoing

    send -null

    if {$lastkey == ""} {
        if $echoing {
            sendcmd "$userbuf"
        }
        if {$procbuf != ""} {
            expcmd "$procbuf"
        }
    } else {
        sendcmd "$userbuf"
        if $echoing {
            expcmd "$procbuf"
            sendcmd "$lastkey"
        }            
    }
    cmd "send -null"
    set userbuf ""
    set procbuf ""
    set lastkey ""
    set echoing 0
}

# Handle a character that came from the process
proc output {s} {
    global lastkey procbuf userbuf echoing

    send_user -raw -- $s

    if {$lastkey == ""} {
        if !$echoing {
            append procbuf $s
        } else {
            sendcmd "$userbuf"
            expcmd "$procbuf"
            set echoing 0
            set userbuf ""
            set procbuf $s
        }
        return
    }

    regexp (.)(.*) $s dummy c tail
    if {$c == $lastkey} {
        if $echoing {
            append userbuf $lastkey
            set lastkey ""
        } else {
            if {$procbuf != ""} {
                expcmd "$procbuf"
                set procbuf ""
            }
            set echoing 1
        }
        append procbuf $s

        if [string length $tail] {
            sendcmd "$userbuf$lastkey"
            set userbuf ""
            set lastkey ""
            set echoing 0
        }
    } else {
        if !$echoing {
            expcmd "$procbuf"
        }
        sendcmd "$userbuf$lastkey"
        set procbuf $s
        set userbuf ""
        set lastkey ""
        set echoing 0
    }
}

# rewrite raw strings so that can appear as source code but still reproduce
# themselves.
proc expand {s} {
    regsub -all "\\\\" $s "\\\\\\\\" s
    regsub -all "\r" $s "\\r"  s
    regsub -all "\"" $s "\\\"" s
    regsub -all "\\\[" $s "\\\[" s
    regsub -all "\\\]" $s "\\\]" s
    regsub -all "\\\$" $s "\\\$" s

    return $s
}

# generate an expect command
proc expcmd {s} {
    global promptmode

    if $promptmode {
        regexp ".*\[\r\n]+(.*)" $s dummy s
    }

    cmd "expect -exact \"[expand $s]\""
}

# generate a send command
proc sendcmd {s} {
    global send_style conservative

    if {$conservative} {
        cmd "sleep .1"
    }

    cmd "send$send_style -- \"[expand $s]\""
}

# generate any command
proc cmd {s} {
    global fd
    puts $fd "$s"
}

proc verbose_send_user {s} {
    global verbose

    if $verbose {
        send_user -- $s
    }
}

proc ctoggle {} {
    global conservative send_style

    if $conservative {
        cmd "# conservative mode off - adding no delays"
        verbose_send_user "conservative mode off\n"
        set conservative 0
        set send_style ""
    } else {
        cmd "# prompt mode on - adding delays"
        verbose_send_user "conservative mode on\n"
        set conservative 1
        set send_style " -s"
    }
}

proc ptoggle {} {
    global promptmode

    if $promptmode {
        cmd "# prompt mode off - now looking for complete output"
        verbose_send_user "prompt mode off\n"
        set promptmode 0
    } else {
        cmd "# prompt mode on - now looking only for prompts"
        verbose_send_user "prompt mode on\n"
        set promptmode 1
    }
}

# quote the next character from the user
proc quote {} {
    expect_user -re .
    send -- $expect_out(buffer)
}


if [catch {set fd [open $filename w]} msg] {
    puts $msg
    exit
}
exec chmod +x $filename
verbose_send_user "autoexpect started, file is $filename\n"

# calculate a reasonable #! line
set expectpath /usr/local/bin        ;# prepare default
foreach dir [split $env(PATH) :] {    ;# now look for real location
    if [file executable $dir/expect] {
        set expectpath $dir
        break
    }
}

cmd "#![set expectpath]/expect -f
#
# This Expect script was generated by autoexpect on [timestamp -format %c]
# Expect and autoexpect were both written by Don Libes, NIST."
cmd {#
# Note that autoexpect does not guarantee a working script.  It
# necessarily has to guess about certain things.  Two reasons a script
# might fail are:
#
# 1) timing - A surprising number of programs (rn, ksh, zsh, telnet,
# etc.) and devices discard or ignore keystrokes that arrive "too
# quickly" after prompts.  If you find your new script hanging up at
# one spot, try adding a short sleep just before the previous send.
# Setting "force_conservative" to 1 (see below) makes Expect do this
# automatically - pausing briefly before sending each character.  This
# pacifies every program I know of.  The -c flag makes the script do
# this in the first place.  The -C flag allows you to define a
# character to toggle this mode off and on.

set force_conservative 0  ;# set to 1 to force conservative mode even if
              ;# script wasn't run conservatively originally
if {$force_conservative} {
    set send_slow {1 .1}
    proc send {ignore arg} {
        sleep .1
        exp_send -s -- $arg
    }
}

#
# 2) differing output - Some programs produce different output each time
# they run.  The "date" command is an obvious example.  Another is
# ftp, if it produces throughput statistics at the end of a file
# transfer.  If this causes a problem, delete these patterns or replace
# them with wildcards.  An alternative is to use the -p flag (for
# "prompt") which makes Expect only look for the last line of output
# (i.e., the prompt).  The -P flag allows you to define a character to
# toggle this mode off and on.
#
# Read the man page for more info.
#
# -Don

}

cmd "set timeout -1"
if $conservative {
    set send_style " -s"
    cmd "set send_slow {1 .1}"
} else {
    set send_style ""
}

if [llength $argv]>0 {
    eval spawn -noecho $argv
    cmd "spawn $argv"
} else {
    spawn -noecho $env(SHELL)
    cmd "spawn \$env(SHELL)"
}

cmd "match_max 100000"

set lastkey ""
set procbuf ""
set userbuf ""
set echoing 0

remove_nulls 0

eval interact $option_keys {
    -re . {
        input $interact_out(0,string)
    } null {
        input_null
    } \
    -o \
    -re .+ {
        output $interact_out(0,string)
    } eof {
        cmd "expect eof"
        return
    } null {
    }
}

close $fd
verbose_send_user "autoexpect done, file is $filename\n"

执行

# exit退出,会在当前目录生成一个script.exp文件
expect autoexpect.exp -p

自己使用例子

打包、上传dev、备份、重启

#!/usr/local/bin/expect -f
#
# Auto pack, scp, restart app by expect.
#
# Use example:
#   ./pack_dev.sh developer 192.140.12.2 pwd /java/workspace-idea-soundbus/bet-game-service /java/workspace-idea-soundbus/bet-game-service/bet-game/target/bet-game.jar /home/developer/sunbar/bet-game-service/bet-game-$(date +'%Y%m%d').jar bet-game /home/developer/sunbar/bet-game-service
#
# Init env(mac os):
#   brew install expect
# 
# Created by suzhida on 2017-08-06 14:47:11

set service_user [lindex $argv 0]
set service_ip [lindex $argv 1]
set service_pwd [lindex $argv 2]

set pack_path [lindex $argv 3]
set scp_source_path [lindex $argv 4]
set scp_to_path [lindex $argv 5]
set app_name [lindex $argv 6]
set service_app_path [lindex $argv 7]

set timeout -1
# bash shell
spawn $env(SHELL)
match_max 100000
expect -exact ""

# pack
send -- "cd $pack_path\r"
expect -exact "cd $pack_path"
send -- "mvn clean install -Dskip.unit.tests=true\r"
expect -exact "mvn clean install -Dskip.unit.tests=true"

# scp 
send -- "scp $scp_source_path $service_user@$service_ip:$scp_to_path\r"
expect -exact "$service_user@$service_ip's password: "
send -- "$service_pwd\r"
expect -exact ""

# restart app
send -- "ssh -p 22 $service_user@$service_ip\r"
expect -exact "$service_user@$service_ip's password: "
send -- "$service_pwd\r"
expect -exact ""
send -- "cd $service_app_path\r"
expect -exact ""
send -- "ln -sf $service_app_path-\$(date +'%Y%m%d').jar $service_app_path-current.jar\r"
expect -exact ""
send -- "./boot.sh\r"
expect -exact ""
send -- "tailf log/spring.log\r"
expect -exact ""

# done 
interact

1) 维基百科介绍
2) 官网
3) 使用expect工具ssh登录远程服务器并执行命令操作
4) expect用法
5) linux expect详解

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值