Tcl 如何发送100多行cmd命令
我希望(tcl)脚本能够正常运行自动任务—通过telnet/ssh配置网络设备。大多数情况下,需要执行1、2或3个命令行,但现在我有100多个命令行要通过expect发送。我如何以智能且良好的脚本编写方式实现这一点:) 因为我可以将超过100个的所有命令行连接到一个变量“commandAll”中,并依次使用“\n”和“send”命令行,但我认为这很难看:)有没有一种方法不将它们堆叠在一起,以便在代码或外部文件中可读Tcl 如何发送100多行cmd命令,tcl,expect,Tcl,Expect,我希望(tcl)脚本能够正常运行自动任务—通过telnet/ssh配置网络设备。大多数情况下,需要执行1、2或3个命令行,但现在我有100多个命令行要通过expect发送。我如何以智能且良好的脚本编写方式实现这一点:) 因为我可以将超过100个的所有命令行连接到一个变量“commandAll”中,并依次使用“\n”和“send”命令行,但我认为这很难看:)有没有一种方法不将它们堆叠在一起,以便在代码或外部文件中可读 #!/usr/bin/expect -f set timeout 20 set
#!/usr/bin/expect -f
set timeout 20
set ip_address "[lrange $argv 0 0]"
set hostname "[lrange $argv 1 1]"
set is_ok ""
# Commands
set command1 "configure snmp info 1"
set command2 "configure ntp info 2"
set command3 "configure cdp info 3"
#... more then 100 dif commands like this !
#... more then 100 dif commands like this !
#... more then 100 dif commands like this !
spawn telnet $ip_address
# login & Password & Get enable prompt
#-- snnipped--#
# Commands execution
# command1
expect "$enableprompt" { send "$command1\r# endCmd1\r" ; set is_ok "command1" }
if {$is_ok != "command1"} {
send_user "\n@@@ 9 Exit before executing command1\n" ; exit
}
# command2
expect "#endCmd1" { send "$command2\r# endCmd2\r" ; set is_ok "command2" }
if {$is_ok != "command2"} {
send_user "\n@@@ 9 Exit before executing command2\n" ; exit
}
# command3
expect "#endCmd2" { send "$command3\r\r\r# endCmd3\r" ; set is_ok "command3" }
if {$is_ok != "command3"} {
send_user "\n@@@ 9 Exit before executing command3\n" ; exit
}
p、 我使用的一种方法是,如果成功执行cmd行,那么cheeking就可以了,但我不确定这是一种完美的方法:D是的,你可以通过这种方式发送长序列的命令,这通常是一个坏主意,因为它使整个脚本非常脆弱;如果发生任何意外情况,脚本将继续强制执行脚本的其余部分。相反,最好在
send
s序列中穿插expect
s以检查您发送的内容是否已被接受。发送很长字符串的唯一实际情况是在另一端创建一个函数或文件,该函数或文件将充当调用的子程序;在这种情况下,没有真正有意义的地方停下来检查中途是否有提示。但这是个例外
请注意,您可以同时期待两件事;这通常非常有用,因为它可以让您直接检查错误。我之所以提到这一点,是因为这是一种经常被忽视的技术,但它允许您使脚本更加健壮
...
send "please run step 41\r"
expect {
-re {error: (.*)} {
puts stderr "a problem happened: $expect_out(1,string)"
exit 1
}
"# " {
# Got the prompt; continue with the next step below
}
}
send "please run step 42\n"
...
不要使用编号的变量,使用列表
set commands {
"configure snmp info 1"
"configure ntp info 2"
"configure cdp info 3"
...
}
如果命令已在文件中,则可以将其读入列表:
set fh [open commands.file]
set commands [split [read $fh] \n]
close $fh
然后,对它们进行迭代:
expect $prompt
set n 0
foreach cmd $commands {
send "$cmd\r"
expect {
"some error string" {
send_user "command failed: ($n) $cmd"
exit 1
}
timeout {
send_user "command timed out: ($n) $cmd"
exit 1
}
$prompt
}
incr n
}
谢谢你,多纳尔。明天我会把你拖到下面:)这就是你的意思对:
#Command-1发送“$command1\r”expect{re{error:(.*)}{puts stderr”发生了一个问题:$expect_out(1,string)“exit 1}”{}Command-2发送“$command2\r”expect{re{re{error:(.}{puts stderr)发生了一个问题:$expect#u out(1,string)“exit 1}”#“{}…我遇到了一些问题。foreach循环工作得很好,但我在它后面又加了一个expect:“expect'$prompt'{send'copy run start'}”,有时会被吸掉!(4次工作-1次没有,等等)我认为是输出缓冲区的问题,因为在循环中,然后我等待同样的事情。你有改进的建议吗。我在foreach循环中写了一些解决方法,我在这里添加了一些想法:“发送“$cmd\r#marker$n”。然后等待同样的事情(不是$prompt,而是#marker$n).但这实际上是发送到设备的#注释:(