On Thursday, January 14, 2021 at 4:10:22 AM UTC+1, HY wrote:
> spawn telnet $ip
> expect -re ".?ogin: "
> send "$username\r"
> expect -re ".?assword: "
> send "$password\r"
From man expect: "The -nocase flag causes uppercase characters of the output to compare as if they were lowercase characters. The pattern is not affected."
In real world examples the .? of the regex is useless (matching is unanchored), and I prefer patterns as strict as possible (fail fast).
> send "sendcmd 1 DB set TelnetCfg 0 Lan_EnableAfterOlt 1\r"
> send "sendcmd 1 DB set PortControl 3 PortEnable 1\r"
> send "sendcmd 1 DB set TelnetCfg 0 TS_Enable 1\r"
> send "sendcmd 1 DB set TelnetCfg 0 Lan_Enable 1\r"
> send "sendcmd 1 DB save\r"
> send "reboot\r"
> expect eof
I'd wait for a prompt before issuing new commands; well, if it works and stability is not a strict requirement, it will probably work.
> I try to re-write it with a more compact form as shown below:
> set prompt "(%|#|>|\\$ )"
> set prompt [string trim $prompt]
There are cases where calculating a constant improves readability, but this does not seem to be the case here.
It does not look like you require the reporting group ().
In Tcl, I use braces for regex.
> expect {
> -re ".?ogin: " { send "$username\r"; exp_continue }
> -re ".?assword: " { send "$password\r"; exp_continue }
Does none of the below commands' output match these?
> -re $prompt {
> send "sendcmd 1 DB set TelnetCfg 0 Lan_EnableAfterOlt 1\r"
> send "sendcmd 1 DB set PortControl 3 PortEnable 1\r"
> send "sendcmd 1 DB set TelnetCfg 0 TS_Enable 1\r"
> send "sendcmd 1 DB set TelnetCfg 0 Lan_Enable 1\r"
> send "sendcmd 1 DB save\r"
> send "reboot\r"
You are probably missing exp_continue here. And you should swap the below lines. eof is a new pattern, not a command in this code block.
> eof
> }
> }
> ---
>
> I'm a newbie of TCL language, and not sure if the rewritten version is correct. Any hints/notes/suggestions/comments/fixes/corrections/touch ups/enhancements are highly appreciated.
I'd probably separate the login from the rest. On a green-field setting, I'd turn off tty echo (stty -echo).
You could have the commands in a list and process them in a loop.
# untested
# this is also a demo of a few useful/fun commands ;-)
set sendcmds {
# do A
1 DB set A
# do B
1 DB set B
# ...
}
set sendcmds [lmap l [split [string trim $sendcmds] \n] {
if {[regexp {^\s*#} $l} continue
string trim $l
}]
# you could move the lmap code to this loop, too
foreach sendcmd $sendcmds {
expect {
-re $prompt {
exp_send "sendcmd $sendcmd\r"
}
}
}
# finally reboot
# alternatively using exp_continue
# no foreach here!
expect {
-re $prompt {
set sendcmds [lassign $sendcmds sendcmd]
exp_send ...
if {[llength $sendcmds]} exp_continue
}
}
HTH
Martin