使用 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
命令更常用于带参数传入的脚本——这就像你传入一个块——但这不是你需要的。)
我有一个 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 aglobal 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
命令更常用于带参数传入的脚本——这就像你传入一个块——但这不是你需要的。)