Autoexpect hang at the end of the script - expect

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

Related

Why '\n'('\r') does not work in my expect script

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

Expect script failing to continue

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

Expect not waiting for prompt - script stops without sending other commands

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.

Shell script with expect module to backup running config of router via console

I am a Linux enthusiast trying my hand at shell scripting lately.
#!/usr/bin/expect-f
cd /home/vuser/Net_backup
now=$(date +"%m_%d_%y")
touch /home/vuser/Net_backup/ASR$now.txt
sleep 5s
set Password "prizer"
set password "banger"
set Trial "32"
set bye "exit"
set quitconsole "q"
set exitcons "logout"
spawn telnet xx.xx.xx.xx
expect "password:"
send "$password\n"
expect "admin>"
send "$Trial\n"
sleep 5s
expect "ASR1001>"
send "enable\n"
expect "Password:"
send "$Password\n"
expect "ASR1001#"
send "terminal length 0\n"
expect "ASR1001#"
send "show run\n" | tee /home/vuser/Net_backup/ASRnow.txt
expect "ASR1001#"
send "$bye\n"
sleep 5s
xdotool key ctrl+]
sleep 5s
send "$quitconsole\n"
expect "admin >"
send "$exitcons\n"
sleep 5s
exit
I intend to write a shell script which would perform the following functions .
(1) Create a file in a specific folder
(2) Append the system date to the file name in the format ""%m_%d_%y""
(3) Login to a console server
(4) access a specific port on a console server to login to the router
(5) go to the super user prompt on the router
(6) set terminal length to 0 to negate the need for carriage return input
(7) run the command "show run" on the router and capture this output to the file created in
step (2)
(8) Exit from the router command prompt
(9)Exit from the console server (this needs three steps first send keystrokes (ctrl+]) then
the command q or quit and finally logout to comeback to the linux prompt)
(10) Exit the script .
I have written the script which is given above ..
My script however gets stuck on the console server and does not move forward, the script proceeds after I manually logout from the console server however the intended output is not achieved
Appreciate your help on this .
Thank you
Avinash
While developing expect scripts, you want to enable debugging output. Always add this near the top: exp_internal 1
This is wrong: #!/usr/bin/expect-f -- you need a space before the option.
Expect is not shell. These lines need to be changed:
now=$(date +"%m_%d_%y")
touch /home/vuser/Net_backup/ASR$now.txt
sleep 5s
send "show run\n" | tee /home/vuser/Net_backup/ASRnow.txt
Use \r instead of \n to "hit enter" for your send commands.
If your expect patterns are correct, there's no need to sleep.
Here's a quick untested rewrite
#!/usr/bin/expect -f
cd /home/vuser/Net_backup
set now [clock format [clock seconds] "%m_%d_%y"]
exec touch ASR$now.txt
set Password "prizer"
set password "banger"
set Trial "32"
set bye "exit"
set quitconsole "q"
set exitcons "logout"
spawn telnet 192.168.95.96
expect "password:"
send "$password\r"
expect "admin>"
send "$Trial\r"
expect "ASR1001>"
send "enable\r"
expect "Password:"
send "$Password\r"
expect "ASR1001#"
send "terminal length 0\r"
expect "ASR1001#"
send "show run\r"
expect -re "(.*)ASR1001#"
set fh [open ASR$now.txt w]
puts $fh $expect_out(1,string)
close $fh
send "$bye\r"
sleep 5
send "^]" ;# here, in your editor, enter a literal ctrl-]
sleep 5
send "$quitconsole\r"
expect "admin >"
send "$exitcons\r"
expect eof
#! /usr/bin/expect -f
set systemTime [clock seconds]
set now [clock format $systemTime -format "%m_%d_%y"]
exec touch ASR$now.txt
set Password "prizer"
set password "banger"
set bye "exit"
set quitconsole "q"
set exitcons "logout"
spawn ssh admin#192.168.95.96
expect "password:"
send "$password\r"
sleep 5
expect "admin>"
send "32\r"
sleep 5
send "\r"
expect "ASR1001>"
send "enable\r"
expect "Password:"
send "$Password\r"
expect "ASR1001#"
send "terminal length 0\r"
expect "ASR1001#"
send "show run \r"
set output [open "ASR$now.txt" "w"] <<<<<<<<<<<<<<< Fails here
send "$bye\r"
sleep 5
send "ctrl-]"
sleep 5
send "$quitconsole\r"
expect "admin>"
send "$exitcons\r"
expect eof
Expect scripting is entirely different from bash scripting. You cannot use bash command inside with expect interpreter.
ie, you cannot use basic commands like tee, cp, mv, rm in expect scripting.
But instead you can configure tftp in you local machine and use the below command in your expect script.
send "copy running-config tftp://$tftp/$config\n\n"
expect "$tftp"
send "\n"
The script should be like,
#!/usr/bin/expect-f
cd /home/vuser/Net_backup
now=$(date +"%m_%d_%y")
touch /home/vuser/Net_backup/ASR$now.txt
sleep 5s
set Password "prizer"
set password "banger"
set Trial "32"
set bye "exit"
set quitconsole "q"
set exitcons "logout"
spawn telnet xx.xx.xx.xx
expect "password:"
send "$password\n"
expect "admin>"
send "$Trial\n"
sleep 5s
expect "ASR1001>"
send "enable\n"
expect "Password:"
send "$Password\n"
expect "ASR1001#"
send "terminal length 0\n"
expect "ASR1001#"
send "copy running-config tftp://$tftp/$config\n\n" #edit this line wrt your local machine's configurations
expect "$tftp"
send "\n"
expect "ASR1001#"
send "$bye\n"
sleep 5s
xdotool key ctrl+]
sleep 5s
send "$quitconsole\n"
expect "admin >"
send "$exitcons\n"
sleep 5s
exit
Here is an working solution. I have tested it using one Cisco device connected to my Debian 9 Stretch VM.
#!/usr/bin/expect -f
cd /var/www/html/Netbackup
set systemTime [clock seconds]
set now [clock format $systemTime -format "%m_%d_%y"]
exec touch R1$now.txt
sleep 1
spawn telnet 192.168.10.100
sleep 1
expect "Username:"
send "cisco\n"
sleep 1
expect "Password:"
send "cisco\n"
sleep 1
expect "R1"
send "terminal length 0\n"
expect "R1#"
send "show run\n"
sleep 2
expect -re "(.*)R1#"
set fh [open /var/www/html/Netbackup/R1$now.txt w]
puts $fh $expect_out(1,string)
close $fh
sleep 1
xdotool key ctrl+]
sleep 1
send "$quitconsole\n"
sleep 1
send "$exitcons\n"
sleep 1
exit
Below are the outputs
root#lampserver:~/Desktop# ./Netbackup.sh
spawn telnet 192.168.10.100
Trying 192.168.10.100...
Connected to 192.168.10.100.
Escape character is '^]'.
User Access Verification
Username: cisco
Password:
R1#terminal length 0
R1#show run
Building configuration...
Current configuration : 2325 bytes
!
............
Output Omitted
............
R1#can't read "bye": no such variable
while executing
"send "$bye\n""
(file "./Netbackup.sh" line 24)
root#lampserver:~/Desktop#
root#lampserver:~/Desktop# cd
root#lampserver:~# cd /var/www/html/Netbackup
root#lampserver:/var/www/html/Netbackup# ls
R102_14_19.txt
root#lampserver:/var/www/html/Netbackup#
root#lampserver:/var/www/html/Netbackup# ls -al
-rw-r--r-- 1 root root 2583 Feb 14 17:49 R102_14_19.txt
root#lampserver:/var/www/html/Netbackup#

Expect Script Terminating on its own

I have written the below expect script but it's not working as expected. I want the script to terminate automatically when all the commands are executed. However , the script either never terminates ( if set timeout -1 is used ) or terminates within seconds even before my commands are executed. Can someone please help ?
Here's the script :
#!/usr/local/bin/expect
spawn su vserve
set password vserve
set PWD whoami
set cmdstr(0) "bash /apps/vpn/vserve/vserve_profile"
set cmdstr(1) "bash /apps/vpn/asap/scripts/change_loopback.sh"
set timeout -1
expect "*Password:*" {
sleep 1
send "$password\r"
send "$PWD\r"
sleep 1
for {set i 0} {$i<[array size cmdstr]} {incr i} {
send "$cmdstr($i)\r"
}
send \"exit\r\"
expect eof
}
Usually in an interactive shell, you have to expect the specific shell prompt before you send next command. That's the way we make sure the previous command has really finished.

Resources