Bssh running Expect

I have a problem with my expect script which I run under a bash script. What it does is take a list of routers and telnets to them and run some commands then to the next router on the list. It works, but the issue I have is if my commands "$cmds" receive a lot of return data, then it gets cut off. I messed around with the timeout but would always cut off data.

expect << EOF
set timeout 60
log_user 0
spawn telnet ${router}
expect "login: "
send "testusername\r"
expect "Password: "
send "testpass\r"
expect "*#"
send "term len 0\r"
expect "*#"
log_user 1
send "$cmds"  
expect "*$router#"
send "exit\r"
EOF

Can you use SSH instead of telnet? That's far more predictable and easily scripted. It also supports normal error reporting over stderr, while telnet can't differentiate. Using keys you can arrange noninteractive remote logins without the gaping security hole of keeping a plaintext password inside your script, too. So all that expect thrashing would boil down to

ssh user@site "$commands" > outputfile 2> errlog

or even

ssh user@site /bin/bash < scriptfile > outputfile 2>errlog

Thanks Corona688, I can ssh to these routers but cannot use keys. So, I still will need the expect Password. Do you have a suggestion on how I would implement that with the ssh statement you provided?

ssh is designed not to accept passwords in that manner. plaintext passwords in script files are security holes big enough to drop a cow through -- and wholly unnecessary when keys can do the same thing securely. Why can't you use keys? All it means is generating one, then adding a line to ~/.ssh/authorized_keys

I think what I need is for each line in my $cmds list, to wait for my expect prompt before the next line is input. Then each line will need to complete before moving to the next line. I read about the while statement but not sure how to implement.

Another theory is that because the speed between server and router the expect keyword is received and exited before the terminal prints the entire output.

Why can't you use keys? You should be able to do so if you can login with ssh. It would allow you to write normal shell scripts for your servers instead of expect scripts that break down all the time and nobody understands. It'd also mean you'd no longer need to embed insecure plaintext passwords inside your script files.

I'm checking with the router manufacture about ssh keys. In the mean time, I tried a coupe of things on my expect script, both failed, trying to expect a prompt after each line in the cmds variable.

foreach element $cmds {
    send $element
    expect "*#"
}
for {set i [expr [llength $cmds]] {$i>=0} {incr i} {
    send "$cmds($i)\r"
    expect "*#"
}

---------- Post updated 04-09-10 at 11:57 AM ---------- Previous update was 04-08-10 at 10:09 PM ----------

I got it working pretty good. I put a unique string at the end of my cmds variable and changed the timeout to 240 right before when the commands are sent.

expect << EOF
set timeout 60
set var "exit    "
log_user 0
spawn telnet ${router}
expect "login: "
send "testusername\r"
expect "Password: "
send "testpass\r"
expect "*#"
send "term len 0\r"
expect "*#"
set timeout 240
log_user 1
send "$cmds"  
expect $var
send "exit\r"
EOF