使用了一段时间Expect自动化工具简介里面的expect脚本,发现少了一些功能:

  1. 怎么给expect脚本传参数呢?
  2. expect怎么调用 bash/sh外部命令呢?
  3. expect怎么操作字符串呢?

tcl

前面的文章Expect命令里面提到过,expect 使用的是Tcl/tk的语法。

所以 大家Google 一下 tcl tutorial就可以解决上面三个问题了。

  1. tcl argc argc

  2. Tcl tutorial

  3. Tcl regexp

new expect script

结合上面的3篇教程我把上篇文章自动化ssh 登陆的脚本优化如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#!/usr/bin/expect -f

# for anyone not familar with expect
# should read this awesome article
# https://www.pantz.org/software/expect/expect_examples_and_tips.html

if { $argc != 1} {
        puts "must set one argument for server_A host ip"
        puts "./login.tcl 1.1.2.2"
        exit 1
}

set timeout 15

#set info [gets stdin]
set info [exec privateRESTfullAPI2GetPwd -host $argv]

set result [regexp {\"([^\"]*)\"[^\"]*\"([^\"]*)\"[^\"]*\"([^\"]*)\"} $info match host pw1 pw2]


send_user "going to connected to server_A\n"
spawn ssh -q -o StrictHostKeyChecking=no nobody@host

expect {
    timeout { send_user "\ntimeout Failed to get password prompt, is VPN on?\n"; exit 1 }
    eof { send_user "\nSSH failure for server_A\n"; exit 1 }
    "*assword:"
}

send "$pwd1\r"

expect {
    timeout {send_user "\nSSH failure for server_B\n"; exit 1 }
    "Last login:*"
}

send "su -\r"
expect {
    eof { send_user "\nSSH failure check your password \n"; exit 1 }
    "密码"
}
send "$pw2\r"

interact

简单解释上面的脚本:

  1. $argc 命令行参数的个数; $argv 命令行参数(不含命令本身);
  2. puts 相当于 bash 的 echo命令 ;
  3. exec 相当于 bash的 $();
  4. privateRESTfullAPI2GetPwd -host $argv 是我本地的一个用来查询主机密码的工具,返回值的格式为:Passworod of "1.1.1.1" are "pwd for noby" and "pwd for root"
  5. 正则表达式 {\"([^\"]*)\"[^\"]*\"([^\"]*)\"[^\"]*\"([^\"]*)\"}用来提取上面privateAPI2GetPwd返回值中3个 双引号中的内容, 即: host, pwd1, pwd2
  6. 命令set result [regexp {...第五条..} $info match host pw1 pw2]把上面正则表达式的的3个 group 分别赋值给 host, pw1, pw2三个变量。 丢弃了resultmatch 两个变量。