使用 tcl proc 登录设备

Using a tcl proc to login to devices

我有一个 tcl (expect) 脚本来登录设备和传输文件。不幸的是,文件很大,并且在传输期间 ssh 连接结束(尽管文件仍在传输)。所以我基本上必须重新登录才能在设备上执行更多操作。由于整个登录过程比较长,所以我放在一个proc中。问题是 proc 登录到设备,但登录后,脚本将命令发送到终端,因为由于某种原因,命令不再到达设备。我不明白为什么我在 proc 中登录的会话没有转移到脚本的其余部分。

proc login {} {
    #login code - it works because I took it from the main script (which works). 
    # variables are all declared as global, no errors are thrown. Login is successful
} 

login

send "show\r" ;# this command is not sent to the device, 
#instead it prints to the terminal. When in the main script, 
#these commands would not be printed to the terminal window. 

我是否遗漏了一个命令,也许 return 登录会话到脚本的其余部分?类似于 interact 命令,但与脚本的其余部分类似。

这是一个棘手的问题。 expect 手册页是这样说的:

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.

所以,添加 global spawn_id 作为 login proc

的第一行

要创建一个在其调用者范围内计算代码的过程,您需要在其中使用 uplevel 命令。这使您可以非常轻松地执行本质上是宏的操作:

proc login {} {
    uplevel {
        # Put your code in here, which might look like this
        spawn ssh user@host ...
        expect Password:
        send $thePassword\r
        expect "bash$"
    }
}

然后,当您使用 login 时,它将 完全 像您在过程中 uplevel 中的命令一样工作,就好像它们会代替 login 调用输入。

这通常不是特别推荐的方法,因为很容易使代码变得不灵活且容易意外中断,但在您的情况下,这是一种非常简单的方法,因为您可以轻松保证只调用login 在整个程序结构中的合理位置。 (uplevel 命令更常用于带参数传入的脚本——这就像你传入一个块——但这不是你需要的。)