Match strings after multiline pattern of texts - bash

I need to extract the value of "Manage VLAN" from the below output with regular expressions and store the value inside a variable to be used later in my script.
set switch 100.10.100.100
set Username "test"
set Password "test"
spawn ssh -o StrictHostKeyChecking=no $Username#$switch
expect "*assword: "
send "$Password\r"
expect *>
send "enable\r"
expect "*#"
send "config\r"
expect "(config)#"
send "display something"
The output will be:
status : Connected
IP Address : 2.2.2.2
Mask : 255.255.255.255
Gateway : 2.2.2.1
Manage VLAN : 456
Manage priority : 0
Option60 : No
Switch : Enable
How might I achieve this?

See example:
expect1.1> spawn bash -c "echo vlan : 1234"
spawn bash -c echo vlan : 1234
22902
expect1.2> expect -re {vlan *: *([0-9]+)}
vlan : 1234
expect1.4> set vlanid $expect_out(1,string)
1234
expect1.5> puts $vlanid
1234
expect1.6>

Related

Expect Script continues execute after ping response

Hello i want To Make A script to test ping after ping success will continues execute comand. Thanks For All Your Helps
below my code
set ip [10.10.10.1,10.10.10.2]
foreach hostname $ip {
spawn ping -c 2 -i 3 -W 1 $hostname
expect { "0%" {
spawn telnet $hostname
expect "*sername:"
send "$userper\n"
expect "*assword:"
send "$passper\n"
expect "#"
send "exit\n"
expect eof
}
}
}
First, this set ip [10.10.10.1,10.10.10.2] will most likely give you invalid command name "10.10.10.1,10.10.10.2"
To make a list, use set ip {10.10.10.1 10.10.10.2} -- braces and spaces.
Next, that ping command does not require any interactivity, so don't spawn it, just exec it:
set ping_output [exec ping -c 2 -i 3 -W 1 $hostname]
And then check the output for 0% -- note, you don't want to match 100% so add a leading space to the pattern:
if {[regexp { 0%} $ping_output]} {
spawn telnet $hostname
...
}
expect is an extension of tcl so all the Tcl commands are at your disposal

expect scripts and old network gear outputs ANSI escape characters

Afternoon,
I have googled this all day and even attempted other solutions in python but not had any success.
I have some old-ish network gear that seems to have a weird terminal type when you SSH to them, the one where CTRL+h is backspace!
This is causing problems for my expect script than needs to do 3 things, 1) log in 2) escalate privileges (think cisco enable) 3) save the config
Tried to set the terminal type but not sure that vt100 is correct, i doubt it is. I also added the sleep commands to see if a delay would solve it, no dice.
here is my script so far
#!/usr/bin/expect
set ::env(TERM) vt100
## Get username
send_user "Username: \n"
expect_user -re "(.*)\n" { set user $expect_out(1,string) }
## Get pass
stty -echo
send_user "Password: \n"
expect_user -re "(.*)\n" { set pass $expect_out(1,string) }
stty echo
## Get list of hosts
set f [ open "hosts.txt"]
set hosts [ split [read $f] "\n"]
set hosts [ lreplace $hosts end end ]
close $f
## iterate host
foreach host $hosts {
spawn ssh "$user\#$host"
expect {
"continue connecting" { send "yes\r"; exp_continue }
"assword" { send "$pass\r" }
}
expect "Copyright (c)" {
sleep 1
send "\r"
sleep 1
send "en 14\r"
sleep 1
send "$pass\r"
sleep 1
send "config save\r"
sleep 1
send "exit\r"
}
}
Output from script
deanmoore#laptop% ./zyxel
Username:
dean.moore
Password:
spawn ssh dean.moore#host1
dean.moore#host1's password:
Copyright (c) 1994 - 2013 ZyXEL Communications Corp.
host1> ^[[47;223R%
deanmoore#laptop% 7;223R

bash/expect/loop - how to loop a simple bash script doing telnet

I would like to run this script in a loop.
What is needs to do is read a file with in that file IP addresses like:
10.0.0.0
10.0.0.1
10.0.0.2
10.0.0.3
10.0.0.4
And run this script on every ip listed above here.
This is what i have:
#!/usr/bin/expect
spawn telnet 10.0.0.0
expect "User Name :"
send "username\r"
expect "Password :"
send "password\r"
expect ">"
send "4\r"
expect "*#"
exit
How do i get the script above working every IP in a txt file.
You can read the file within your expect script.
Open the file and assign the file descriptor to a variable, read each line and execute the above code you wrote.
set fildes [open "myhosts.txt" r]
set ip [gets $fildes]
while {[string length $ip] > 0} {
spawn telnet $ip
expect "User Name :"
send "username\r"
expect "Password :"
send "password\r"
expect ">"
send "4\r"
expect "*#"
exit
set ip [gets $fildes]
}
close $fildes
I'm not an expert with expect, but the first thing you need to do is change your expect script to accept arguments. It should work like this (looks like you'll need -f in #!/usr/bin/expect):
#!/usr/bin/expect -f
set ip [lindex $argv 0]
spawn telnet $ip
...
Then you can simply iterate over the list of your IPs in your bash script:
while read ip ; do
myExpectScript $ip
done < list_of_ip.txt
This is just a comment on #user3088572's answer. The idiomatic way to read a file line by line is:
set fildes [open "myhosts.txt" r]
while {[gets $fildes ip] != -1} {
# do something with $ip
}
close $fildes

Error no route to host using expect while reading host user name and passwords from a csv file

I writing a script to read user name, password and host info from a file.
I then parse this info to get the variables. I would then like to add these variables to an expect script that reads all the ip address in my file and performs certain commands on the remote devices that I am trying to log into. The script works when it connects to a known host however What I am seeing is that there is one device that is not up and running and the system promps with the following error.
ssh: connect to host 192.168.3.2 port 22: No route to host
the file
I would like to do 2 things
1. Skip the host and move to the next host
2. log the host that is down to another file so that I can troubleshoot the network issue to that host.
Please see the script below. Please any help is greatly accepted.
#! /usr/bin/expect -f
## Read the file
set fid [open /csv_pars/employee1.csv]
set content [read $fid]
close $fid
## Split into records on newlines
set records [split $content "\n"]
## Iterate over the records
foreach rec $records {
## Split into fields on comma
set fields [split $rec ","]
## Assign fields to variables and print some out...
lassign $fields\ ipaddr username password
puts "$ipaddr"
puts "$username"
puts "$password"
if {$ipaddr == ""} continue
spawn ssh -X "$username#$ipaddr"
sleep 2
expect "password:"
sleep 2
send "$pass\r"
expect "$"
send -- "ls -l\r"
expect "$"
send -- "exit\r"
expect eof
}
You need to expect to see one of two things: the password prompt, or the error message:
spawn ssh -X "$username#$ipaddr"
expect {
-re "password: ?$" {
send "$pass\r"
expect "$"
send -- "ls -l\r"
expect "$"
send -- "exit\r"
expect eof
}
"No route to host" {
set fid [open error.log a]
puts $fid "[clock format [clock seconds]]: No route to host $ipaddr"
close $fid
}
}

Run cat on remote computer and send output a variable using expect

I have a bash+expect script which has to connect via ssh to the remote comp (and i can't use ssh keys, need password identification in here), read the file there, find specific line with the "hostname" (like "hostname aaaa1111") and store this hostname into the variable to be used after while. How can i get the value of the "hostname" parameter? I thought that line content will be in $expect_out(buffer) variable (so i can scan it and analyze), but it's not. My script is:
#!/bin/bash
----bash part----
/usr/bin/expect << ENDOFEXPECT
spawn bash -c "ssh root#$IP"
expect "password:"
send "xxxx\r"
expect ":~#"
send "cat /etc/rc.d/rc.local |grep hostname \r"
expect ":~#"
set line $expect_out(buffer)
puts "line = $line, expect_out(buffer) = $expect_out(buffer)"
...more script...
ENDOFEXPECT
When i try to see line variable, i see only this: line = , expect_out(buffer) = (buffer) What is the right way to get the line from the file into the variable?
Or is it possible to open the file on the remote computer with expect, scan the file and get what i need to the variable?
Here http://en.wikipedia.org/wiki/Expect there is an example:
# Send the prebuilt command, and then wait for another shell prompt.
send "$my_command\r"
expect "%"
# Capture the results of the command into a variable. This can be displayed,
set results $expect_out(buffer)
seems that it doesn't work in this case?
You might just want to try and do it all from expect, as expect can control bash.
The following should do what you've described. Not sure if this is exactly what you are trying to do.
#!/bin/sh
# the next line restarts using tclsh \
exec expect "$0" "$#"
spawn bash
send "ssh root#$IP\r"
expect "password:"
send "xxxx\r"
expect ":~#"
send "cat /etc/rc.d/rc.local |grep hostname \n"
expect ":~#"
set extractedOutput $expect_out(buffer)
set list [split $extractedOutput "\n"]
foreach line $list {
set re {(?x)
.*
(*)
-S.*
}
regexp $re $line total extractedValue
if {[info exists extractedValue] && [string length $extractedValue] > 1} {
set exportValue $extractedValue
break # We've got a match!
}
send "exit\r" # disconnect from the ssh session
if {[info exists exportValue] && [string length $exportValue] > 1}{
send "export VARIABLE $exportValue\r"
} else {
send_user "No exportValue was found - exiting\n"
send "exit\r"
close
exit 1
}
# now you can do more things in bash if you like

Resources