How to save output expect in bash - bash

I am trying to make a script to save a output of the command show version in cisco.
I need made a connection to one server for that the ssh connection, and then i have connection with the device.
In the file out.txt, I have the output of the first connection, the ssh connection, but i dont know how to save the output of the show version
#!/usr/bin/expect -f
#!/bin/sh
spawn ssh -l user x.x.x.x
expect "login as:"
expect "password:"
send "password\r"
expect "$\r"
send "telnet nemonic\r"
expect "$\r"
expect "login:"
send "user\r"
expect "password:"
send "password\r"
expect "*>"
send "terminal length 0\r"
send "show version \r"
expect "*>"
set results $expect_out(buffer)
set config [open out.txt w]
puts $config $results
close $config
send "exit\r"
expect eof
send "\r"
send "exit\r"
Could you help me?
Best regards

I solve with
log_file -noappend status.txt
after the command show version
Thank you && Best Regards

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

bash script which downloads a file with sftp

I need to make a sftp connection with a password and download a file. There is an ip restriction so first of all i should make a ssh connection. I wrote a script but it stucks after connecting with ssh.
Note: i also tried doing it with an expect script but it also didn't work.
#!/usr/local/bin/
ssh test#test1.t.com
lftp sftp://test2:123456#test2.com
get "file.xls"
Edit: You can also see my expect code here.
#!/usr/local/bin/expect -f
expect -c "
spawn ssh test#test1.t.com
expect \"test\#test1\:\~\$\"
spawn sftp test2#test2.com
expect \"*assword:\"
send \"123456\r\"
expect \"sftp\>\"
send \"get file.xls\r\"
expect \"sftp\>\"
exit 1
";
I'm not sure exactly what you're trying to accomplish here. First, I'll address the problems in your expect script. Since your shebang line invokes expect, you don't need to wrap the expect body in a call to expect. That gets rid of all the backslashes. Next, you have 2 spawn calls, which raises questions about you're intent. I'm going to assume that you want to ssh to test1, then grab the file from test2 so the file exists on test1. This assumption changes the 2nd spawn to a plain send command.
#!/usr/local/bin/expect -f
set shell_prompt "test#test1:~$"
set sftp_prompt "sftp>"
spawn ssh test#test1
expect $shell_prompt
send "sftp test2#test2\r"
expect "*assword:"
send "123456\r"
expect $sftp_prompt
send "get file.xls\r"
expect $sftp_prompt
send "exit\r"
expect $shell_prompt
send "exit\r"
expect eof
Now, you can scp the file to your local machine. Let's put those 2 steps into one shell script:
#!/bin/sh
expect <<'EXPECT_SCRIPT'
set shell_prompt "test#test1:~$"
set sftp_prompt "sftp>"
spawn ssh test#test1
expect $shell_prompt
send "sftp test2#test2\r"
expect "*assword:"
send "123456\r"
expect $sftp_prompt
send "get file.xls\r"
expect $sftp_prompt
send "exit\r"
expect $shell_prompt
send "exit\r"
expect eof
EXPECT_SCRIPT
scp test#test1:file.xls .

BASH: Send directory files from server(non-sftp) to remote server that use sftp

I can send files one by one by changing the file name, the files are increasing in number so I tried using for loop but it did not work.
I need to send all the files in FILE variable to the remote machine USER#$HOST:/Semi/KFILE-ENG/ELD. Also, the remote machine is sftp enabled, while the sender is using ftp only.
This is what I only have.
HOST=ftpabc.abc.cn
PORT=22
USER=user
PASSWORD=pass
FILE=/u01/flatringDev/ToVendor/LC7/ELD/ELD.7
spawn /usr/bin/sftp $USER#$HOST:/Semi/KFILE-ENG
expect "password:"
send "$PASSWORD\r"
expect "sftp>"
send "mkdir ELD\r"
expect "sftp>"
send "cd ELD\r"
expect "sftp>"
send "put $FILE\r"
expect "sftp>"
send "bye\r"
If someone knows a solution, please let me know. Thank you
#!/bin/bash
HOST=ftpabc.abc.cn
PORT=22
USER=user
PASSWORD=pass
declare -a arry
arry=('file1' 'file2' 'file3' 'file4' '/tmp/kl.pl') # list files with absolute path eg: /tmp/kl.pl
#for FILE in $(ls -1 DIR_containing_files) # If you can all files in same dir, else create an array with elements as filenames with absoulte path and use 2nd for statement
for FILE in ${arry[*]}
do
spawn /usr/bin/sftp $USER#$HOST:/Semi/KFILE-ENG
expect "password:"
send "$PASSWORD\r"
expect "sftp>"
send "mkdir ELD\r"
expect "sftp>"
send "cd ELD\r"
expect "sftp>"
send "put $FILE\r"
expect "sftp>"
send "bye\r"
sleep 5
done
Check if this works, you can have a bash function doing all the expect thing and call it in for loop
or an expect script file and call that in bash for

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#

Pipe stdin into "expect" script

I am uploading a file via ftp using expect. The file is piped into my bash script.
#!/bin/bash
HOST='example.com'
USER='XXX'
PASSWD='XXX'
expect << EOT
spawn ftp $HOST
expect "Name*:"
send "$USER\r"
expect "Password:"
send "$PASSWD\r"
expect "ftp>"
send "binary\r"
expect "ftp>"
send "prompt\r"
expect "ftp>"
send "put - $1\r" ####
expect "ftp>"
send "bye\r"
expect eof
EOT
On the highlighted line I want ftp to get access to the main script stdin.
Thank you
I believe the key to what you are looking for is Expect's interact command. You'd get a script like this:
#!/usr/bin/env expect
# Set these in the Tcl way, not the bash way
set HOST "example.com"
set USER "XXX"
set PASSWD "YYY"
# You should recognize this bit...
spawn ftp $HOST
expect "Name*:"
send "$USER\r"
expect "Password:"
send "$PASSWD\r"
expect "ftp>"
send "binary\r"
expect "ftp>"
send "prompt\r"
expect "ftp>"
# New stuff starts here
send "put - [lindex $argv 0]\r"
interact {
"ftp>" { return }
}
send "bye\r"
wait
exit
I've rewritten your script so it doesn't use a here document, because that would have interfered with the reading of the content (here-docs are presented as stdinā€¦) and switched it to use a few more idiomatic ways of doing things (idiomatic argument access being the main one).
That said, if I was doing this sort of thing for real, I'd look into using the ftp package from Tcllib as that talks the protocol directly instead of using a possibly-problematic subprocess. (Indeed, if you were going to be doing this on Windows, you'd have to do it that way because of quirks of how Expect and FTP.EXE work on that platform).

Resources