expect-auto-login

之前写过两篇blog,介绍通过 public_key来服务器自动登陆以及使用expect脚本来登陆,后来发现服务器多了的话每个服务器写一个脚本太不现实了,就考虑写一个通用的脚本,通过传参以及读取配置文件来实现自动登陆。看下改造完之后的脚本。

第一种,通过expect脚本读取配置文件。

text.exp文件

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#!/usr/bin/expect
proc getConfig {configFile Key {Comment "#"} {Equal "="}} { ;#过程中如果参数有缺省值,使用花括号引起,并赋值
set Value "" ;# 记录过程返回的值
# 打开配置文件
set err [catch {set fileid [open $configFile r]} errMsg]
if {$err == 1} {
puts "errMsg : $errMsg"
return $Value
}
# 成功打开文件后, 一行一行的加以分析
set rowid 0 ;#记录当前行数,程序调试时打印调试信息使用的
while {[eof $fileid] != 1} { ;# 读取文件内容
incr rowid ;# 记录行数, 从一开始
gets $fileid line ;# 读出一行
# 先去掉注释, 再去掉两端的空格
set commentpos [string first $Comment $line] ;# 得到注释符号的位置
if { $commentpos == 0 } {
# 行以注释符号开头,忽略掉该行
} else {
if { $commentpos != -1 } { ;# 行中有注释符号,去掉注释
set line [string range $line 0 [expr $commentpos-1]]
}
set line [string trim $line] ;# 去掉两端的空格
#puts "$rowid : line : $line"
# 如果是空就继续循环
if { $line == "" } {
continue
} else {
set equalpos [string first $Equal $line] ;# 得到等号的位置
if { $equalpos != -1} {
# 如果就是找寻的key,结束循环
if { [string range $line 0 [expr $equalpos - 1]] == $Key } {
set Value [string range $line [expr $equalpos + 1] [string length $line]]
break
}
}
}
}
}
# 关闭文件
close $fileid
#返回值
return $Value
}
#getConfig可以传参获取到指定的参数值
set server [lindex $argv 0] #获取到命令行传得参数值
set user [getConfig "/shell/config.yml" ${server}_user ]
set port [getConfig "/shell/config.yml" ${server}_port]
set password [getConfig "~/shell/config.xml" ${server}_password]
set ip [getConfig "~/shell/config.xml" ${server}_ip]
set timeout 15
spawn ssh $user@$ip -p $port
expect {
"(yes/no)" { send "yes\r"; exp_continue }
"*assword:" { send "$password\r" }
}
interact

config.yml

1
2
3
4
5
6
7
8
9
server1_ip=139.129.1.2
server1_user=root
server1_password=test
server1_port=80
server2_ip=139.129.1.3
server2_user=root
server2_password=test
server2_port=80

只要配置好config文件,就可以通过执行命令

1
2
./text.exp server1 #登陆服务器1
./text.exp server2 #登陆服务器2

第二种,自动登陆的方式,也是使用expect,不通过exepct来读取配置文件,需要装一个软件jq,通过jq来解析json,找到配置文件里指定的字段,这个方法是老大写的^~^。(jq在这里可以下载)

text.exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/expect
set sign [lindex $argv 0]
set timeout 200
set params {port user pwd ip}
foreach param $params {
set $param [exec cat servers.json | jq ".$sign.$param" | tr -d '""' ]
}
spawn ssh -p$port $user@$ip
expect {
"(yes/no)" { send "yes\r"; exp_continue }
"*assword:" { send "$pwd\r" }
}
interact

servers.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"server1": {
"ip": "123.1.2.1",
"port": "80",
"user": "root",
"pwd": "1111"
}
}
{
"server2": {
"ip": "123.1.2.2",
"port": "80",
"user": "root",
"pwd": "1111"
}
}

同样通过执行命令

1
2
./text.exp server1 #可登陆server1
./text.exp server2 #可登陆server2