I'm creating an expect script to let me use macros in my managing of cisco devices.
after all the connections are done, my script waits for the "#" so I know the user is ready for input. if I define my procedure AFTER interact, script works fine, but obviously it hasn't been declared yet so the script fails. if I define it BEFORE interact, I time out like it's actually "expecting"
why would this procedure "run" without even being called?
proc portSec {port} {
send "show port interface $int\r"
expect {
-nocase -re "(invalid)|(ambig}" {
puts "\nInvalid Interface\n"
return
}
-nocase -re "(\[0-9\]+.\[^ \]+.\[^ \]+):\[^ \]" {
set mac $expect_out(1,string)
}
}
~~~~expect "#" ~~~~~~
send "show port address \| i $mac\r"
expect "#"
}
interact {
"!p" {
send_user "\nWelcome to macro mode!\nWhich interface would you like to clear port security?: "
stty echo
expect_user -re "(.*)\r" {
set port $expect_out(1,string)
}
stty -echo
portSec $port
send "\r"
}
}
Here is the debug
expect: does " \r\nYour password will expire in 1 week, 5 days, 3 hours,
44 minutes and 56 seconds
\r\r\n\r\nHOSTNAME line 1 \r\n\r\nHOSTNAME#" (spawn_id exp4)
match glob pattern "#"? yes
expect: set expect_out(0,string) "#"
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) " \r\nYour password will expire in 1 week,
5 days, 3 hours, 44 minutes and 56 seconds\r\r\n\r\nHOSTNAME line 1
n\r\nHOSTNAME#"
expect: does "" (spawn_id exp4) match glob pattern "#"? no
expect: timed out
can't read "mac": no such variable
while executing
"send "show port address \| i $mac\r""
(file "./ios.exp" line 78)
stepping through the debugger, I tilded "~~~" the line where it's expecting
Oh!!! Poor me. How come I missed this mistake!!! :-D
After banging my head for a lot, found that you have used close braces by mistake in the expect statement.
-nocase -re "(invalid)|(ambig}" {
Changing it to bracket, solves this issue. :-)
proc portSec {port} {
send "show port interface $int\r"
expect {
-nocase -re "(invalid)|(ambig)" {
puts "\nInvalid Interface\n"
return
}
-nocase -re {\[0-9\]+.\[^ \]+.\[^ \]+):\[^ \]} {
set mac $expect_out(1,string)
}
}
expect "#";#
send "show port address \| i $mac\r"
expect "#"
}
It all makes sense now. But, why Expect didn't throw any error as such? Then Why it has to accept the remaining part of braces as correct one ?
Well, Because of the misplaced close brace, Expect assumes that the it closes the first expect statement. The code segment remaining are
# two code segments enclosed in braces
# 'Expect' assumes these two as pattern-action pair
# which is why no errors thrown for these blocks.
{
puts "\nInvalid Interface\n"
return
}
-nocase -re "(\[0-9\]+.\[^ \]+.\[^ \]+):\[^ \]" {
set mac $expect_out(1,string)
}
};# This one closes the proc 'portSec'
####### Below code is now in global scope #########3
expect "#"; # Now, wait for '#'
# Send this command now, but wait...
# I don't know about the variable 'mac'
send "show port address \| i $mac\r"
expect "#"
Thereby throwing the error message as can't read "mac": no such variable.
Final product:
#port security clear feature
proc clearPortSec {} {
send_user "\n=====\nWelcome to the Port Security Macro!!!!!\nWhich interface would you like to clear port security?: "
#interact seems to turn of user echoing... turn it back on so the user can make changes
stty echo
expect_user -re "(.*)\r" {
set port $expect_out(1,string)
}
stty -echo
#send ctrl+u to clear the line, and send ctrl+z so we know we are in enable mode
send "\025\032\r"
expect "#"
#verify it is explicitly an access port, if not we don't do the operations to prevent trunks from being shut
send "sho run int $port \| i switchport mode access\r"
expect {
-nocase -re "\r\n\[ \]*switchport mode access\[ \]*\r\n.*#" {
send "\rshow port interface $port\r"
expect {
#grabs offending mac address on this port
-nocase -re "(\[0-9\]+.\[^ \]+.\[^ \]+):\[^ \]" {
set mac $expect_out(1,string)
expect "#"
#finds where switch learned the offending mac
send "show port address \| i $mac\r"
expect {
#case where switch learned mac from another interface
-nocase -re "sticky +(\[^ \]+)" {
set offendport $expect_out(1,string)
puts "\n=====\nMac was found on interface $offendport. Clearing $offendport\n====="
#clear port mac was found on
expect "#"
send "\rconf t\r"; expect "#"
send "interface $offendport\r"; expect "#"
send "no switchport port-security mac-address sticky\r"; expect "#"
send "switchport port-security mac-address sticky\r"; expect "#"
send "shut\r"; expect "#"
send "no shut\r;" expect "#"
#switch to original port
send "interface $port\r"; expect "#"
send "no switchport port-security mac-address sticky\r"; expect "#"
send "switchport port-security mac-address sticky\r"; expect "#"
send "shut\r"; expect "#"
send "no shut\r"; expect "#"
#end all operation and print status of each port
send "end\r"; expect "#"
send "wr\r"; expect "#"
puts "\n=====\nSleeping a few seconds..\nPrevious port will NOT be shut. Please shut if necessary\n====="
send "show int $offendport status\r"; expect "#"
send "show int $port status\r"; expect "#"
}
#case where switch never learned mac
"#" {
puts "\n=====\nMac is no where else on the switch, clearing existing sticky mac from $port\n====="
send "\rconf t\r"; expect "#"
send "interface $port\r"; expect "#"
send "no switchport port-security mac-address sticky\r"; expect "#"
send "switchport port-security mac-address sticky\r"; expect "#"
send "shut\r"; expect "#"
send "no shut\r"; expect "#"
send "end\r"; expect "#"
send "wr\r"; expect "#"
puts "\n=====\nSleeping a few seconds..\n====="
sleep 3
send "show int $port status\r"
}
}
}
}
}
#if we get back '%' - input error, if we get back '#' switchport mode access doesn't exist
-re "\[%#\]" {
puts "\n=====\nInvalid Interface\nThis script ignores all interfaces that don't have \"Switchport mode access\"\n====="
send "\r"
}
}
}
# Don't check keys
spawn ssh -o StrictHostKeyChecking=no $username\#$hostname
expect {
"assword:" {
interact -o -re "\[#>\]" return {
puts "\nLog in Complete"
}
}
timeout {
puts "=====\n$hostname timeout\n====="
exit 1
}
eof {
exit 1
}
}
send "\n"
expect "#"
set timeout -1
interact {
-re "!\[Hh\]" {
puts "\n=====\nMacro list\n=====\nPort Security: !p\n\n"
send "\r"
expect "#"
}
"!p" { clearPortSec }
}
Related
I'm running a MANET simulation in ns2 using AODV routing protocol. Is there any way I can check whether a node forwards data it receives to the next node in the route or check whether the link between 2 nodes is active?
Try this:
package require http
package require tls
http::register https 443 [list ::tls::socket -tls1 1]
set url "https://google.com"
if {![catch {set token [::http::geturl $url]} msg]} {
if {[::http::status $token] == "ok"} {
#Do something when token is ok for example print HTTTP code
puts [::http::code $token]
} else {
#Do something when status token is not ok
}
} else {
#print error when Url is invalid or host is unreachable
puts "oops: $msg"
}
I need to check if URL is working properly or not using "PowerShell Version 2.0"
I found this script over internet, but it is not wokring fine for wrong URL's. It should go in else loop for wrong URL's as well as print website code. And I am not able to pass credentials in this script.
e.g. for www.google.com(correct URL) status code should be 200but
for www.gfjgugy79rt9(Wrong URL) status code should be something like 404
script I found over internet for powershell version 2.0:
# First we create the request.
$HTTP_Request = [System.Net.WebRequest]::Create('http://google.com')
# We then get a response from the site.
$HTTP_Response = $HTTP_Request.GetResponse()
# We then get the HTTP code as an integer.
$HTTP_Status = [int]$HTTP_Response.StatusCode
If ($HTTP_Status -eq 200) {
Write-Host "Site is OK!"
}
Else {
Write-Host "The Site may be down, please check!"
}
# Finally, we clean up the http request by closing it.
$HTTP_Response.Close()
In PowerShell higher than 2.0 you should use try ... catch ... finally because this code fire exception when the URI is no conform or when the adress part is not solvable by the DNS :
try {
# First we create the request.
$HTTP_Request = [System.Net.WebRequest]::Create('http://google.com')
# We then get a response from the site.
$HTTP_Response = $HTTP_Request.GetResponse()
# We then get the HTTP code as an integer.
$HTTP_Status = [int]$HTTP_Response.StatusCode
If ($HTTP_Status -eq 200) {
Write-Host "Site is OK!"
}
Else {
Write-Host "The Site may be down, please check!"
}
}
catch {
Write-Verbose $_.ScriptStackTrace
Write-Verbose "Ligne $($_.InvocationInfo.ScriptLineNumber) : $($_.exception.message)"
}
finally {
# Finally, we clean up the http request by closing it.
$HTTP_Response.Close()
}
In PowShell 2.0 you just have to put a Trap code at the beginnig of the scope (function, script) where you want to catch these exception :
trap
{
Write-Verbose $_.ScriptStackTrace
Write-Verbose "Ligne $($_.InvocationInfo.ScriptLineNumber) : $($_.exception.message)"
Write-Verbose ([datetime]::Now)
return
}
Within my expect script expect_after to catch the timeout coming from BadPromptPassword, however how do I return that this was the place that my expect script timed out? I've played with expect_out and it doesnt give me what I need... Any help appreciated. Thanks
spawn telnet 172.27.228.239
expect {
timeout { puts "Timed out waiting for response from telnet ('172.27.228.230',)."; exit 1}
"Password:" { send "lab\r"; }
"\[>#\]"
};
send "en\r"
expect_after {
timeout {
puts "a default timeout clause for all subsequent expect commands ";
exit 1
}
}
expect "#>"
send "admin"
expect "BadPromptPassword:"
send "lab\r"
close
wait
Here's a quick hack
expect_after {
timeout {
puts "timed-out expecting $pattern";
exit 1
}
}
set pattern "#>"
expect $pattern
send "admin"
set pattern "BadPromptPassword:"
expect $pattern
send "lab\r"
I have a tcl script to log into devices and print SUCCESS. This is the script:
The file: (the first IP is valid, and can be logged into, the next 3 are fake).
192.38.133.145
178.18.34.48
183.24.56.3
145.234.67.145
The script:
#!/bin/expect
package require Expect
set file [open "hosts" r]
set f_data [read $file]
set data [split $f_data "\n"]
foreach host $data {
set timeout 8
if {$host > 0} {
## GETS THE HOST IP##
set host_ip $host
##LOGS INTO THE DEVICE##
spawn ssh test#$host_ip
expect {
"password:" {
puts "SUCCESS"
} timeout {
puts "Could not connect to host: ${host_ip}"
#break
}
}
send "password\r"
expect ">"
send "en\r"
}
}
If I do not include the break, I get the message could not connect to host, but instead of looping to the next host, it sends "en\r".
when I do include the break, it gives the message that it cannot reach the host (the second IP, which is expected) and the script ends there (it does not process the 3rd IP). How do I cannot seem to get it to process the 3rd and 4th IPs.
I used the method suggested by potrzebie in this thread: TCL: loops How to get out of inner most loop to outside?
and still cannot get it to work
break should work. The expect man page has this to say in the documentation for the expect command:
Actions such as break and continue cause control structures (i.e., for, proc) to behave in the usual way.
I'd write your loop like this:
foreach host $data {
# very basic data validation: an ipv4 address contains some dots
if {[string match {*.*.*.*} $host]} {
spawn ssh test#$host
expect {
"password:" {
puts "SUCCESS"
send "password\r"
exp_continue
}
timeout {
puts "Could not connect to host: $host"
continue
}
">" {
# I see a prompt. Fall out of this "expect loop"
}
}
send "en\r"
expect ">"
# do something to close the connection
send "exit\r"
expect eof
}
}
I'm trying to work with the phpwebsocket library at http://code.google.com/p/phpwebsocket/
I'm using the version r8 of the server.php file. For testing I just tried with the client.html file, also provided by the website.
When the server is started I get this:
Server Started : 2011-08-29 22:11:23
Master socket : Resource id #4
Listening on : www.midomain.com port 12345
But when I load the client.html file in the browser, the server shows the following errors:
Notice: Undefined variable: key1 in /home/mink500/public_html/test/server.php on line 143
Notice: Undefined variable: key2 in /home/mink500/public_html/test/server.php on line 143
Warning: socket_select(): 5 is not a valid Socket resource in /home/mink500/public_html/test/server.php on line 15
There are two variables that are not defined, and the function socket_select() returns the error "5 is not a valid Socket resource"
In the browser I get the "Disconnected" message as soon as the file is loaded.
I tried to make the server work locally using XAMPP (Apache and PHP) but I got the same errors. I also tried to change ports and follow the instructions in this issue:
http://code.google.com/p/phpwebsocket/issues/detail?id=33
But I still get the error "5 is not a valid Socket resource"
I remember that refreshing the page several times I got it running a few months ago, but now it's impossible. Besides, I need it to work all the time, not just after I refresh the page like 20 times.
I also tried with the websocket.class.php file, but this time I get an error on the client side. The browser now returns "Error during WebSocket handshake: 'Sec-WebSocket-Accept' header is missing".
So, I can't make it work with old or new files, with remote or local server, with magic or a ouija board!
Any idea?
Thanks
Starting with the newest phpwebsocket client.html and server.php files I replaced both the getheaders() and dohandshake() functions with the code below works for me in newest Chrome. However it currently does not write to the browser nor stay alive after one uer comment in the chat box.
function dohandshake($user, $buffer) {
$key = null;
console("\nRequesting handshake...");
console($buffer);
console("Handshaking...");
preg_match("#Sec-WebSocket-Key: (.*?)\r\n#", $buffer, $match) && $key = $match[1];
$key .= "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
$key = sha1($key);
$key = pack('H*', $key);
$key = base64_encode($key);
$upgrade =
"HTTP/1.1 101 Switching Protocols\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"Sec-WebSocket-Accept: {$key}\r\n\r\n";
socket_write($user->socket, $upgrade . chr(0), strlen($upgrade . chr(0)));
$user->handshake = true;
console($upgrade);
console("Done handshaking...");
return true;
}
function getheaders($header) {
$retVal = array();
$fields = explode("\r\n", preg_replace('/\x0D\x0A[\x09\x20]+/', ' ', $header));
foreach ($fields as $field) {
if (preg_match('/([^:]+): (.+)/m', $field, $match)) {
$match[1] = preg_replace('/(?<=^|[\x09\x20\x2D])./e', 'strtoupper("\0")', strtolower(trim($match[1])));
if (isset($retVal[$match[1]])) {
$retVal[$match[1]] = array($retVal[$match[1]], $match[2]);
} else {
$retVal[$match[1]] = trim($match[2]);
}
}
}
if (preg_match("/GET (.*) HTTP/", $header, $match)) {
$retVal['GET'] = $match[1];
}
return $retVal;
}