Before this is chalked up as a timeout, or max_match issue, I will say that I have tried those. I have also tried using full_buffer, but it seems the only fix is to put a sleepafter theexpect when a large output comes before it. It's almost as if the expect ">$" is seen and processed by expect before the terminal can print the output.
term len 0 is a cisco command to basically prevent the default | more of the file
Example:
set timeout -1
spawn ssh host
expect "assword:"
send "$pass\r"
expect ">$"
send "term len 0\r"
expect ">$"
set size_orig [match_max]
match_max 60000000
send "show start\r"
expect ">$"
does not work. The output of "show start" is stopped x lines into the output.
If I put handling for timeout and full_buffer, the same thing happens:
set timeout -1
spawn ssh host
expect "assword:"
send "$pass\r"
expect ">$"
send "term len 0\r"
expect ">$"
set size_orig [match_max]
match_max 60000000
set timeout -1
send "show start\r"
expect {
timeout {
send $expect_out(buffer)
}
full_buffer {
send $expect_out(buffer)
}
">$" {
append outcome $expect_out(buffer)
}
}
The only way I was able to fix this was adding a sleep after the expect ">$" (I did this in the simple script below, and also in the script which handles full_buffer and timeout) :
set timeout -1
spawn ssh host
expect "assword:"
send "$pass\r"
expect ">$"
send "term len 0\r"
expect ">$"
set size_orig [match_max]
match_max 60000000
set timeout -1
send "show start\r"
expect ">$"
sleep 10
This works, but is there a proper way to do this as opposed to making the script wait by sleeping? Not all of the devices have such large outputs, so the sleep is not needed on each host.
one additional test I made was running the script with expect -d and the following was at the end of the truncated ouput:
tty_set: raw = 3, echo = 0
Thanks,
chris
The following resolved the issue in my script by suppressing the output displayed to the user, and rather, appending it to my log_file :
log_file -a initial_commands
log_user 0
send "some commands with large output"
log_file
log_user 1
In this case it does not matter whether the user sees the output, as I am parsing it and outputting it to a file anyway. To further disprove it was an error in my expect "<$" code, I experienced this same behavior (by complete accident) when running system "parse.pl". That perl script simply read the large output of show start and printed it line by line. Sure enough, the output stopped short and the script stopped. If anyone would like to dive deeper into this issue, please let me know and I can gladly provide more info.
Related
I want to input y+enter to reply the question while executing copy tftp:something.
The script will send y, but \n does not work. It will stay (y/n)y and keep there without exiting or doing something else. I have tried \r, and the result was the same. Does anyone know the reason?
#!bin/bash
expect -c "
set timeout -1
spawn telnet x.x.x.x
expect \"username\"
send \"user\n\"
expect \"password\"
send \"pw\n\"
expect \"model\"
send \"copy tftp:something\n\"
expect \"(y/n)\"
send \"y\n\"
expect eof
"
exit 0
I prefer using \r to "hit enter".
Second, your entire bash script is expect, so remove the outer bash layer.
#!/usr/bin/expect -f
set timeout -1
spawn telnet x.x.x.x
expect "username"
send "user\r"
expect "password"
send "pw\r"
expect "model"
send "copy tftp:something\r"
expect "(y/n)"
send "y\r"
expect eof
If you have more logic in the bash part, to avoid quoting hell use a heredoc:
#!/bin/bash
expect <<'END_EXPECT'
set timeout -1
spawn telnet x.x.x.x
expect "username"
send "user\r"
expect "password"
send "pw\r"
expect "model"
send "copy tftp:something\r"
expect "(y/n)"
send "y\r"
expect eof
END_EXPECT
exit 0
I'm running the following autoexpect script
#!/usr/bin/expect -f
set force_conservative 0 ;# set to 1 to force conservative mode even if
;# script wasn't run conservatively originally
if {$force_conservative} {
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s -- $arg
}
}
set timeout -1
spawn $env(SHELL)
match_max 100000
send -- "ssh f.olivieri#10.255.255.1\r"
expect -exact "Password: "
send -- "C4n4r1Wh4rf!!!\r"
expect -exact "887VA#"
send -- "show interface vlan 2\r"
expect -exact "Vlan2 is up, line protocol is up \r"
send -- "logout\r"
expect eof
When I run it, seems that it doesn't terminate itself correctly and I don't have back my bash shell. Only If I press ctrl+c i get my terminal
[...]
0 output buffer failures, 0 output buffers swapped out
887VA#logout
Connection to 10.255.255.1 closed by remote host.
Connection to 10.255.255.1 closed.
root#blackbox:/etc/myscripts#
I don t have
my bahs
shell
^Croot#blackbox:/etc/myscripts#
-bash: I: command not found
root#blackbox:/etc/myscripts#
This is a problem for me because I need to run that script within a bash script and save the output on txt file and then edit it
I have an expect script which is logging onto a device and sending a command, however the script completes without finishing, its like the last expect isn't being picked up.
How do I enable debugging to watch the script progress so I can identify where the issues is?
My script looks like this...
#!/usr/bin/expect
set hostname [lindex $argv 0]
set username "a.user"
set password "a.pass"
spawn telnet $hostname
expect "Username:" {
send "$username\r"
expect "Password:"
send "$password\r"
}
expect "#" {
send "sh ver\r"
}
It stops processing at the below line;
expect "#" {
however I can clearly see the # in the last output.
Thanks
I have expect script which I run to get some export of the live Network, but I have a stupid issue now. Script connect's to smotool, and log file to myfile.log, but today it won't work. Well when I put exp_internal 1 or log_user 1 it's working fine, otherwise not. It's really stupid and annoying but I don't know does anyone have idea what could I include in code. I want to hide the output, that's why I can't use log_user 1.
Sory if question is in some hand stupid:)
#!/usr/local/bin/expect
match_max 1000
exp_internal 0
log_user 0
set timeout 180
spawn smotool
log_file myfile.log
set prompt smo.*
expect -re $prompt
send -- "listnes -full"
expect -re $prompt
Here's the code that I have, I explain how I want it to work at the bottom.
set 11 "10.0.0.101"
set 12 "10.0.0.12"
set timeout 20
spawn telnet $11
expect {
"Unable to connect to remote host:" {exit}
"login:"
}
send "root\r"
expect "Password:"
send "root\r"
expect "#"
send "shutdown -r now\r"
expect "#"
send "exit\r"
expect "Connection closed by foreign host."
set timeout 20
spawn telnet $12
expect "login:"
send "root\r"
expect "Password:"
send "root\r"
expect "#"
send "shutdown -r now\r"
expect "#"
send "exit\r"
expect "Connection closed by foreign host."
exit
As you can see, I am using this to reboot devices once a week with a crontab, but if the device is not responding or offline, the script just stops at {exit}
So I want to use like goto command or similar to run the next spawn command in the list.
Is there any easy way to do this if there is no goto command ?
Maybe you can include all your command exchange for the first server within the block of code executed after the login prompt is successfully matched?
Something like the following:
set 11 "10.0.0.101"
set 12 "10.0.0.12"
set timeout 20
spawn telnet $11
expect {
"Unable to connect to remote host:" { }
"login:" {
send "root\r"
expect "Password:"
send "root\r"
expect "#"
send "shutdown -r now\r"
expect "#"
send "exit\r"
expect "Connection closed by foreign host."
}
}
spawn telnet $12
[...]
If after attempting to connect to $11 you get an "Unable to connect...", it will execute the empty block and move on. If it matches the "login:", it will execute all commands.
You will need to check whether your telnet closes successfully after the "Unable to connect" message (I would think it does), so that you don't end up with multiple spawned sessions.