加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

用expect命令实现Shell的自动化交互

发布时间:2020-12-15 09:13:34 所属栏目:安全 来源:网络整理
导读:背景 linux脚本中有很多场景是进行远程操作的,例如远程登录ssh、远程复制scp、文件传输sftp等。这些命令中都会涉及到安全密码的输入,正常使用命令时是需要人工手动输入密码并接受安全验证的。为了实现自动化远程操作,我们可以借用expect的功能。 expect e

背景

linux脚本中有很多场景是进行远程操作的,例如远程登录ssh、远程复制scp、文件传输sftp等。这些命令中都会涉及到安全密码的输入,正常使用命令时是需要人工手动输入密码并接受安全验证的。为了实现自动化远程操作,我们可以借用expect的功能。

expect

expect的核心是spawn、expect、send、set。

spawn 调用要执行的命令

expect 等待命令提示信息的出现,也就是捕捉用户输入的提示:
send 发送需要交互的值,替代了用户手动输入内容
set 设置变量值
interact 执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。
expect eof 这个一定要加,与spawn对应表示捕获终端输出信息终止,类似于if....endif

expect脚本必须以interact或expect eof结束,执行自动化任务通常expect eof就够了。

其他设置

  • 设置expect永不超时 set timeout -1
  • 设置expect 300秒超时,如果超过300没有expect内容出现,则退出 set timeout 300

expect编写语法

expect使用的是tcl语法

  • 一条Tcl命令由空格分割的单词组成. 其中,第一个单词是命令名称,其余的是命令参数
    cmd arg arg arg
  • $符号代表变量的值. 在本例中,变量名称是foo.
    $foo
  • 方括号执行了一个嵌套命令. 例如,如果你想传递一个命令的结果作为另外一个命令的参数,那么你使用这个符号
    [cmd arg]
  • 双引号把词组标记为命令的一个参数. "$"符号和方括号在双引号内仍被解释
    "some stuff"
  • 大括号也把词组标记为命令的一个参数. 但是,其他符号在大括号内不被解释
    {some stuff}
  • 反斜线符号是用来引用特殊符号. 例如:n 代表换行. 反斜线符号也被用来关闭"$"符号,引号,方括号和大括号的特殊含义

示例

login.exp专用于远程登录,快捷使用方式: login.exp "exclude" "${remote_ip}" "${remote_user}" "${remote_passwd}" "${remote_command}"

#!/usr/bin/expect -f
##########################################################
# 通过SSH登陆和执行命令
#参数:1.Use_Type [check/execute]
#     2.SSHServerIp
#     3.SSHUser
#     4.SSHPassword
#     5.CommandList [多个命令间以;间隔]
#返回值:
#     0  成功
#     1  参数个数不正确
#     2  SSH 服务器服务没有打开
#     3  SSH 用户密码不正确
#     4  连接SSH服务器超时
##########################################################

proc usage {} {
    regsub ".*/" $::argv0 "" name
    send_user "Usage:n"
    send_user "    $name Use_Type SSHServerIp SSHUser SSHPassword CommandListn"
    exit 1
}
  
## 判断参数个数
if {[llength $argv] != 5} {
    usage
}

#设置变量值
set Use_Type [lindex $argv 0]
set SSHServerIp [lindex $argv 1]
set SSHUser [lindex $argv 2]
set SSHPassword [lindex $argv 3]
set CommandList [lindex $argv 4]

#spawn ping ${SSHServerIp} -w 5
#expect {
#    -nocase -re "100% packet loss" {
#        send_error "Ping ${SSHServerIp} is unreachable,Please check the IP address.n"
#        exit 1
#    }
#}

set timeout 360
set resssh 0
#定义变量标记ssh连接时是否输入yes确认
set inputYes 0
set ok_string LOGIN_SUCCESS
if {$Use_Type=="check"} {
    #激活ssh连接,如果要需要输入yes确认,输入yes,设置inputYes为1,否则输入ssh密码
    spawn ssh ${SSHUser}@${SSHServerIp} "echo $ok_string"
} else {          
    spawn ssh ${SSHUser}@${SSHServerIp} "$CommandList"
}
expect {
    -nocase -re "yes/no" {
        send -- "yesn"
        set inputYes 1
    }
    -nocase -re "assword: " {
        send -- "${SSHPassword}n"
        set resssh 1
    }
   #-nocase -re "Last login: " { 
   #     send -- "${CommandList}n"
   #}
    $ok_string {}
    -nocase -re "Connection refused" {
        send_error "SSH services at ${SSHServerIp} is not active.n"
        exit 2
    }
    timeout {
        send_error "Connect to SSH server ${SSHUser}@${SSHServerIp} timeout(10s).n"
        exit 4
    }
}

#如果输入了yes确认,输入ssh密码
if {$inputYes==1} {
    expect {
        -nocase -re "assword: " {
            send -- "${SSHPassword}n"
            set resssh 1
        }
    }
}

#如果出现try again或者password:提示,说明输入的用户密码错误,直接退出。
if {$resssh==1} {
    expect {
        -nocase -re "try again" {
            send_error "SSH user:${SSHUser} passwd error.n"
            exit 3
        }
        -nocase -re "assword:" {
            send_error "SSH user:${SSHUser} passwd error.n"
            exit 3
        }
        eof {}
    }
}
send_error -- "$expect_out(buffer)"
#-nocase -re "No such user" {
#        send_error "No such user.n"
#        exit 5
#    }
#exit

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读