- 论坛徽章:
- 0
|
本帖最后由 npc_hp110 于 2014-08-31 10:07 编辑
【问题介绍】
一般的Linux系统可以通过ssh user@ip command远程执行命令
但某些特殊的定制化系统,ssh登录后会进入定制化的人机交互进程(非shell环境),无法通过上述方式远程管理
通过expect可以实现ssh登录后的自动化控制,但是要事先把交互逻辑写入expect脚本中,通用性差。
【解决方法】
expect脚本采用tcl语法,原生态地支持socket。因此考虑用expect做一个ssh中转服务器
1,中转服务器先ssh登录系统,进入人机交互环境
2,然后启动一个socket服务器等待客户端的连接
3,当客户端发来交互命令时直接转发给spawn的ssh子进程处理
4,并将命令处理结果发送回客户端
以下是一段简单的代码,服务器端代码:- #!/usr/bin/expect -f
- set timeout 60
- set user XXX
- set ip XXX
- set passwd XXX
- set prompt XXX
- set sent_passwd 0
- spawn ssh $user@$ip
- expect {
- "yes/no" { send "yes\r";exp_continue }
- "passwd" {
- if { $send_passwd == 0 } {
- send "$passwd\r";
- set send_passwd 1
- exp_continue
- } else {
- puts "passwd may be wrong"
- exit 1
- }
- }
- "$prompt" { }
- }
- #以上代码实现ssh登录系统
- set ssh_agent [ socket -server accept 12345 ]
- proc accept { client addr port } {
- puts "new client connected($addr:$port)"
- gets $client cmd
- send "$cmd\r"
- expect "(.*)$prompt"
- set result_list [ split $expect_out(1,string) "\n" ]
- for line $result_list { #似乎puts每次只能发送一行内容??
- puts $client $line
- }
- puts $client "<result_end>" #发送结束标识
- flush $client
- close $client
- }
- vwait forever
复制代码 客户端代码:- #!/usr/bin/expect -f
- set cmd [join $argv " "]
- set client [socket 127.0.0.1 12345]
- puts $client $cmd
- flush $client
- while { 1 == 1 } {
- gets $client line
- if { $line == "<result_end>" } {
- break
- }
- puts $line
- }
- close $client
复制代码 上述代码没有经过严格测试(其实没有经过任何测试^_^),请大家批评指正。
【遗留问题】
expect中启动的socket服务器,当有客户端连接时,会执行accept函数。不同的客户端的accept函数似乎是并行执行的(可能是在不同线程中)
因此如果有多个客户端同时发送命令到服务器端,可能会有多个accept函数同时运行,会产生一些问题:
1,有可能会同时发送多条命令到ssh子进程,多条命令组合可能形成非法命令
2,输出结果混在一起,无法区分是那个客户端的命令执行结果
请问大神们,如何在accept函数上加上互斥锁的机制,让它同一时刻只能处理一个客户端的命令请求?
我现在想到的方法是在shell脚本中调用客户端,调用的时候用woodie大神的脚本串行化方法加锁
http://bbs.chinaunix.net/forum.p ... st%3D1%26digest%3D1 |
|