Tcl 如何发送100多行cmd命令

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

我希望(tcl)脚本能够正常运行自动任务—通过telnet/ssh配置网络设备。大多数情况下,需要执行1、2或3个命令行,但现在我有100多个命令行要通过expect发送。我如何以智能且良好的脚本编写方式实现这一点:) 因为我可以将超过100个的所有命令行连接到一个变量“commandAll”中,并依次使用“\n”和“send”命令行,但我认为这很难看:)有没有一种方法不将它们堆叠在一起,以便在代码或外部文件中可读

#!/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).但这实际上是发送到设备的#注释:(