ssh - 如何在 TCL Expect 中的多个程序之间共享生成的 SSH 进程?

标签 ssh tcl expect procedure procedures

编辑:我通过引用《Exploring Expect》一书找到了答案。不过,请随时添加我的答案或提出其他建议!当我被允许时(从现在起 2 天后),我会将其标记为已回答。

我环顾四周,不幸的是我在这个网站上找不到太多关于使用 SSH 和 Expect 的信息。我对 Expect 还比较陌生,但我一直在通过《Exploring Expect》一书自学。

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

示例:(该示例被简化了很多,只包含了演示我的问题所必需的组件...到目前为止,我的整个程序已超过 200 行)

;# Proc definition for procedure1
    proc procedure1 {user host pw} {
     spawn /usr/bin/ssh $user@$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 $user@$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

如何将命令从 procedure2 发送到 procedure1 中打开的 SSH 连接,而不是在 procedure1 结束时关闭 SSH 连接并在 procedure2 开始时重新打开 SSH 连接?显然,我必须删除发送退出以保持连接打开。假设这是可能的......这是否是一个好的实践,或者我最好分离过程之间的连接?如果是这样,您可以修改我的代码示例来演示如何操作吗?

根据我收集的信息,我认为这与 spawn_id 变量有关。但我不知道如何在我的代码中实现它。我目前正在复习《Exploring Expect》一书中的第 10 章“处理多个进程”。如果我能自己解决的话,我会报告。

感谢您的帮助!

我在 stackoverflow 上查看了这些答案:

Tcl Expect Keep SSH Spawn open

Expect Procedure for SSH Login

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

最佳答案

您可以使用global申报spawn_id作为一个全局变量。根据expect的手册:

CAVEATS

...
Expect takes a rather liberal view of scoping. In particular, variables read by commands specific to the Expect program will be sought first from the local scope, and if not found, in the global scope. For example, this obviates the need to place global timeout in every procedure you write that uses expect. On the other hand, variables written are always in the local scope (unless a global command has been issued). The most common problem this causes is when spawn is executed in a procedure. Outside the procedure, spawn_id no longer exists, so the spawned process is no longer accessible simply because of scoping. Add a global spawn_id to such a procedure.
...


您还可以利用 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] $

关于ssh - 如何在 TCL Expect 中的多个程序之间共享生成的 SSH 进程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44600154/

相关文章:

tcl - 在文件中查找搜索字符串并打印该行中的下一个单词

c++ - 编译 Tcl/tk 时出错

linux - 命令 ssh server2 后询问密码

node.js - SFTP createReadStream 未写入 s3 存储桶

json - 通过 SSH 运行复杂的 sed 命令时出现问题

linux - bash脚本的奇怪行为

tcl - 获取 tcl 8.4 中的行号

linux - 嵌入式期望脚本返回 bash 成功或失败

perl - 在 Ubuntu 中从 perl 脚本运行 Tcl(期望)脚本的命令

tcl - 关于 Expect 中的 expect_out(buffer)