公司登录日志服务器要求先登上一个中间服务器(即常说的跳板机), 再通过中间服务器登录到目标服务器。
这个过程操作麻烦, 主要有如下问题:
- 登录中间服务器需要账号和密码
- 登录到中间服务器之后, 需要通过ssh方式登录目标服务器。
- 登录目标服务器之后需要cd到相应的日志目录下
整体思路是:
- 将目标服务器的树状结构写到配置文件中去
- 将中间服务器以及目标服务器的账号密码也写到配置文件中
- 登录服务器时输入相应的参数, 如项目名称, 模块名称, 机器序号等
首先分享一个使用expect/tcl读取ini配置文件的wiki: 点击打开链接
接下来expect脚本代码
#!/usr/bin/expect
namespace eval cfg {
variable version 1.0
variable sections [list DEFAULT]
variable cursection DEFAULT
variable DEFAULT; # DEFAULT section
}
proc cfg::sections {} {
return $cfg::sections
}
proc cfg::variables {{section DEFAULT}} {
return [array names ::cfg::$section]
}
proc cfg::add_section {str} {
variable sections
variable cursection
set cursection [string trim $str \[\]]
if {[lsearch -exact $sections $cursection] == -1} {
lappend sections $cursection
variable ::cfg::${cursection}
}
}
proc cfg::setvar {varname value {section DEFAULT}} {
variable sections
if {[lsearch -exact $sections $section] == -1} {
cfg::add_section $section
}
set ::cfg::${section}($varname) $value
}
proc cfg::getvar {varname {section DEFAULT}} {
variable sections
if {[lsearch -exact $sections $section] == -1} {
error "No such section: $section"
}
return [set ::cfg::${section}($varname)]
}
proc cfg::parse_file {filename} {
variable sections
variable cursection
set line_no 1
set fd [open $filename r]
while {![eof $fd]} {
set line [string trim [gets $fd] " "]
if {$line == ""} continue
switch -regexp -- $line {
^#.* { }
^\\[.*\\]$ {
cfg::add_section $line
}
.*=.* {
set pair [split $line =]
set name [string trim [lindex $pair 0] " "]
set value [string trim [lindex $pair 1] " "]
cfg::setvar $name $value $cursection
}
default {
error "Error parsing $filename (line: $line_no): $line"
}
}
incr line_no
}
close $fd
}
set projectType [lindex $argv 0]
set moduleType [lindex $argv 1]
set hostIndex [lindex $argv 2]
set configPath config/config.ini
cfg::parse_file $configPath
set jump_host $cfg::jump_server(host)
set jump_port $cfg::jump_server(port)
set jump_user $cfg::jump_server(username)
set jump_pwd $cfg::jump_server(password)
set log_user $cfg::log_server(username)
set log_pwd $cfg::log_server(password)
set log_port $cfg::log_server(port)
set configPath config/$projectType.ini
cfg::parse_file $configPath
set projectName $cfg::main(project_name)
set moduleName [cfg::getvar module_name $moduleType]
set host [cfg::getvar host_$hostIndex $moduleType]
set time -1
spawn ssh -p $jump_port $jump_user@$jump_host
expect "$jump_user@$jump_host's password:" {
send "$jump_pwd\r"
}
expect "$jump_user:~\\\$" {
send "ssh -p $log_port $log_user@$host\r"
}
expect "$log_user@$host's password:" {
send "$log_pwd\r"
}
expect "$log_user:~\\\$" {
send "cd /var/log/$projectName/$moduleName/logs\r"
}
interact
需要说明的是, 如果section是固定的,可以使用$cfg::SECTIONNAME(KEYNAME)的方式
如果section是变量, 则需要使用 [cfg::getvar key section]方式调用,
另外, expect的具体使用方式网上可以搜到很多, 这里就不多说了
另外, 配个我这边的配置文件结构
第一张图是通用配置, 第二张图片是每个项目的配置, 一般可以考虑一个项目一个配置文件, 根据项目简称找到项目的配置文件, 读取相应的模块配置即可