2017-06-17 61 views
2

编辑:我已经通过引用Exploring Expect书来解决它。但请不要犹豫,添加我的答案或提出其他建议,但!当我被允许时(从现在起2天),我会将其标记为回答。如何在TCL Expect中的多个过程之间共享衍生的SSH过程?

我环顾四周,很遗憾,我无法在本网站上使用SSH期望过多。我对Expect相对来说比较陌生,但我一直在用Exploring Expect这本书教我自己。

我的问题是:如何为多个tcl程序使用单个衍生的SSH进程?我现在的解决方法是在程序1结束时关闭SSH连接,并在程序2中重新生成一个新的SSH连接。

示例:(该示例简化了很多步骤,仅包含必要的组件我的问题...我的整个计划是200线,截至目前)

;# Proc definition for procedure1 
    proc procedure1 {user host pw} { 
    spawn /usr/bin/ssh [email protected]$host 
    expect "Password:" 
    send "$pw\r" 
    expect "#" ;# This is my device's prompt 
    ;# From here it does a bunch of stuff... sends commands to the SSH 
    ;# session, captures output, builds arrays and lists, etc 
    send "exit" ;# Disconnects the SSH session 
    return $mylist ;# returns a list of numbers to be used in procedure 2 
    } 

;# Proc definition for procedure2 
    proc procedure2 {resultofproc1 user host pw} {  
    spawn /usr/bin/ssh [email protected]$host 
    expect "Password:" 
    send "$pw\r" 
    expect "#" ;# This is my device's prompt 
    ;# Proc 2 now continues on in the same device using the results (a 
    ;# list) from proc1. 
    return 
    } 



    ;# Procedure call for first procedure: 
    set resultofproc1 "[procedure1 $user $host $pw]" 

    ;# Procedure call for second procedure: 
    procedure2 $resultofproc1 $user $host $pw 

,而不是关闭在程序1月底的SSH连接,并在重新开放的过程2开头的SSH连接,我怎么能发送命令从procedure2到在procedure1中打开的SSH连接?很明显,我将不得不删除发送出口,以保持连接打开。假设这是可能的...这是一个很好的做法,还是我最好分离程序之间的连接?如果是这样,你可以修改我的代码示例来演示如何?

从我收集的,我认为它与spawn_id变量..但我不知道如何在我的代码中实现。我目前正在阅读探索期望书中的第10章“处理多个进程”。如果我可以自行解决,我会报告回来。

感谢您的协助!

我已经查看了这些答案在计算器:

Tcl Expect Keep SSH Spawn open

Expect Procedure for SSH Login

Using procedure for spawing SSH doesn't work properly with expect

回答

0

啊,我是如此接近!如果我在“探索期望书”中再花几分钟时间,我会想清楚的。无论如何,这是我的解决方案。希望它可以帮助其他人解决同样的问题。

它与spawn_id变量有关。基本上,默认情况下,send和expect命令只与最后产生的进程交互。每个产生的进程都被赋予一个唯一的spawn_id值。您可以将过程的spawn_id设置为另一个衍生进程的spawn_id。

下面是修改以支持spawn_id在变量在我原来的问题代码:

;# Proc definition for procedure1 
    proc procedure1 {user host pw} { 
    spawn /usr/bin/ssh [email protected]$host 
    global procedure1_spawnid   ;# Creates a global variable called 
             ;# procedure1_spawnid 
    set procedure1_spawnid $spawn_id ;# Assigns the spawn_id of the SSH process to the 
             ;# global variable. 
    expect "Password:" 
    send "$pw\r" 
    expect "#" ;# This is my device's prompt 
    ;# From here it does a bunch of stuff... sends commands to the SSH 
    ;# session, captures output, builds arrays and lists, etc 
    return $mylist ;# returns a list of numbers to be used in procedure 2 
    } 

;# Proc definition for procedure2 
    proc procedure2 {resultofproc1} {  
    global procedure1_spawnid 
    set spawn_id $procedure1_spawnid ;# Sets the spawn_id to that of the SSH connection 
             ;# in procedure1. 
    send "show ip interface brief" 
    expect "#" 
    ;# The show ip interface brief command is sent to the device through the 
    ;# SSH connection opened in procedure1. 
    return 
    } 



    ;# Procedure call for first procedure: 
    set resultofproc1 "[procedure1 $user $host $pw]" 

    ;# Procedure call for second procedure: 
    procedure2 $resultofproc1 

更多信息可以在探索期待可以发现,233

如果任何人有任何建议或改进页面,请随时把它们放在我身上!我仍然在学习tcl/expect。

2

您可以使用global来声明spawn_id作为全局变量。据预计手册:

CAVEATS

...
期待需要作用域的一个相当自由的观点。特别是,通过特定于期望程序的命令读取的变量将首先从本地范围寻求,并且如果未找到,则在全局范围中。例如,这可避免在您使用expect编写的每个过程中放置​​global timeout。另一方面,写入的变量始终在本地范围内(除非已发出global命令)。这导致最常见的问题是在过程中执行spawn。在程序之外,spawn_id不再存在,所以产生的过程不再仅仅因为作用域而被访问。添加一个global spawn_id到这样的程序。
...


您也可以利用Tcl的upvar命令。例如:

[STEP 101] $ cat foo.exp 
proc expect_prompt {} { 
    upvar spawn_id spawn_id 
    expect -re {bash-[.0-9]+[#$] $} 
} 

proc open_conn {} { 
    upvar spawn_id spawn_id 
    spawn bash --noprofile --norc 
    expect_prompt 
} 

proc close_conn {} { 
    upvar spawn_id spawn_id 
    send "exit\r" 
    expect eof 
} 

proc send_cmd { cmd } { 
    upvar spawn_id spawn_id 
    send "$cmd\r" 
    expect_prompt 
} 

proc main {} { 
    open_conn 

    send_cmd "echo spawn_id=$spawn_id" 
    send_cmd "ps Tu" 

    close_conn 
} 

main 
[STEP 102] $ 

输出:

[STEP 103] $ expect foo.exp 
spawn bash --noprofile --norc 
bash-4.4$ echo spawn_id=exp6 
spawn_id=exp6 
bash-4.4$ ps Tu 
USER  PID %CPU %MEM  VSZ RSS TT STAT STARTED  TIME COMMAND 
root 71513 0.0 0.0 2433012 788 s013 R+ 12:58PM 0:00.00 ps Tu 
pynexj 71510 0.0 0.0 2445360 1572 s013 Ss 12:58PM 0:00.01 bash --noprofile --norc 
bash-4.4$ exit 
exit 
[STEP 104] $ 
+0

感谢whjm!我将更多地关注upvar与全球变量的想法。 – David00

+0

手册中提取的内容意味着你只需要在'open_conn'进程中使用'global spawn_id',你可以从所有其他helper procs中移除'upvar'命令。他们将自动从全局范围获取spawn_id。这个例外是在'main' proc中,你明确引用了var:那里,你可以使用'$ :: spawn_id'从全局范围中获取它。 –

+0

@glennjackman - 我同意'全球'是足够的,更容易对大多数情况下。处理多个spawn或编写库代码时,'upvar'更好。 – pynexj

相关问题