#!/usr/bin/perl -w #=============================================================================# # Program: sw_cmd # # Author: Chad Kerner # #-----------------------------------------------------------------------------# # Purpose: Instead of running expect scripts to work with the Brocade # # switches, I converted it expect scripts to perl. # # # #-----------------------------------------------------------------------------# # History: # # 20040311 - Chad Kerner - Initial Coding # # 20040316 - Chad Kerner - # # 1. Changed login logic to work on Brocade 12000 switches. # # 2. Modified regex for matching the command prompt. # # 3. Added logic to allow the commands to be run on the switch to be placed # # in a file for execution. # # 4. Added logic to remove the Control-M's from the output. # # 5. Added logic to prompt for the password for every switch specified. # # 6. Added some basic error checking. # # 20040318 - Chad Kerner - # # 1. Modified logic for multiple commands to only connect to the switch one # # time instead of once for each command. # #=============================================================================# #-----------------------------------------------------------------------------# # Package Declarations # #-----------------------------------------------------------------------------# use strict; use Net::Telnet; use Getopt::Long; use Term::ReadKey; #-----------------------------------------------------------------------------# # Function Prototypes # #-----------------------------------------------------------------------------# sub check_options(); sub print_help_screen(); sub get_password($); sub handle_error($); #-----------------------------------------------------------------------------# # Variable Declarations # #-----------------------------------------------------------------------------# $main::continue = 'Type to continue, Q to stop:'; $main::password = ""; $main::logfile = ""; $main::cmdfile = ""; $main::userid = ""; $main::command = ""; #-----------------------------------------------------------------------------# # Main Code Block # #-----------------------------------------------------------------------------# { my $switch; my $command; my $ok; my $errmsg; check_options(); if( $main::logfile ne "" ) { open(LOGFILE,">$main::logfile") || die("Unable To Open File: $main::logfile\n"); $main::print_log = 1; } else { $main::print_log = 0; } foreach $switch (@main::switches) { my $sw_prompt = '/.*:' . "$main::userid" . '> /'; if ( $main::checkpass && ! $main::interactive ) { $main::password = get_password($switch); $main::checkpass = 0; } elsif( $main::interactive ) { $main::password = get_password($switch); } my $sw = new Net::Telnet (Timeout => 10, Errmode => 'return', Prompt => '/.*login: /' ); # Establish a connection with the switch. $ok = $sw->open("$switch"); if( ! $ok ) { handle_error($sw->errmsg); } # Wait for the login prompt. $ok = $sw->waitfor(Match => '/.*login: /', Timeout => 10); if( ! $ok ) { handle_error($sw->errmsg); } # Send the user id. $ok = $sw->print("$main::userid"); if( ! $ok ) { handle_error($sw->errmsg); } # Waid for the password prompt. $ok = $sw->waitfor(Match => '/.*assword: /', Timeout => 10); if( ! $ok ) { handle_error($sw->errmsg); } # Send the password. $ok = $sw->print("$main::password"); if( ! $ok ) { handle_error($sw->errmsg); } # Wait for the command prompt. $ok = $sw->waitfor(Match => $sw_prompt, Timeout => 20); if( ! $ok ) { handle_error($sw->errmsg); } foreach $command (@main::cmds) { if( ! $main::print_log ) { print "### Switch: $switch\tCommand: $command\n"; } else { print LOGFILE "### Switch: $switch\tCommand: $command\n"; } # Send the command. $ok = $sw->print("$command"); if( ! $ok ) { handle_error($sw->errmsg); } LINE: while( (my $text) = $sw->waitfor(Match => $sw_prompt, String => $main::continue, Timeout => 120) ) { $text =~ s/^\s+//; # Strip Leading Spaces $text =~ s/\s+$//; # Strip Trailing Spaces $text =~ s/\cM//g; # Strip Control-M last LINE if $text =~ m/^$/; chomp $text; if( ! $main::print_log ) { print "$text\n"; } else { print LOGFILE "$text\n"; } $sw->print(""); } if( ! $main::print_log ) { print "\n\n"; } else { print LOGFILE "\n\n"; } } # Close the connection. $ok = $sw->close(); if( ! $ok ) { handle_error($sw->errmsg); } } # If the logfile is open, close it before exiting. if( $main::print_log ) { close(LOGFILE); } exit; } # End of the main code block. #-----------------------------------------------------------------------------# # This routine will check the command line options. #-----------------------------------------------------------------------------# sub check_options() { # If no command arguments are specified, print the help screen. if( scalar @ARGV == 0 ) { print_help_screen(); } my $result = GetOptions ( 's=s' => \$main::switch, 'u=s' => \$main::userid, 'p=s' => \$main::password, 'i' => \$main::interactive, 'o=s' => \$main::logfile, 'f=s' => \$main::cmdfile, 'h' => sub { print_help_screen(); }, ); # Combine the rest of the command line into the brocade command. foreach(@ARGV) { $main::command = $main::command . " " . $_; } @main::switches = split(/,/,$main::switch); if( scalar @main::switches == 0 ) { print "\n\tYou must specify at least 1 switch.\n\n"; exit; } if( $main::userid eq "" ) { $main::userid = "admin"; } if( $main::password eq "" ) { $main::checkpass = 1; } else { $main::checkpass = 0; } if( $main::cmdfile eq "" ) { if( $main::command ne "" ) { push @main::cmds, $main::command; } } else { open(CMDFILE,"$main::cmdfile") || die("Unable To Open File: $main::cmdfile\n"); foreach () { chomp; s/^\s+//; # Remove leading whitespace s/\s+$//; # Remove trailing whitespace next if /^$/; # Skip blank lines next if /^#/; # Skip comment lines s/\s*#.*//; # Skip partial comment lines push @main::cmds, $_; } close(CMDFILE); } # If no commands are specified, print the help screen. if( scalar @main::cmds == 0 ) { print_help_screen(); } return; } # End of the check_options() routine. #-----------------------------------------------------------------------------# # This routine will print the generic help screen. #-----------------------------------------------------------------------------# sub print_help_screen() { print STDERR "\n\n"; print STDERR "\tUsage: sw_cmd -s -u -p \n"; print STDERR "\t -i -o -f \n\n"; print STDERR "\tOptions:\n\n"; print STDERR "\t-s\tComma seperated list of switches\n"; print STDERR "\t-u\tUserid to connect with(admin by default)\n"; print STDERR "\t-p\tPassword of the account being used\n"; print STDERR "\t-i\tPrompt for the password for each switch\n"; print STDERR "\t-o\tFile to hold the command output\n"; print STDERR "\t-f\tFile containing a list of commands to run on the switches\n"; print STDERR "\n\t \tCommand to execute\n\n"; exit; } # End of the print_help_screen() routine. #-----------------------------------------------------------------------------# # This routine gets the password from the prompt. #-----------------------------------------------------------------------------# sub get_password($) { my $switch = $_[0]; my $passwd; print STDERR "Enter $main::userid password for $switch: "; ReadMode 'noecho'; $passwd = ReadLine 0; chomp $passwd; ReadMode 'normal'; print STDERR "\n"; return $passwd; } # End of the get_password() routine. #-----------------------------------------------------------------------------# # This routine will handle the telnet object errors. #-----------------------------------------------------------------------------# sub handle_error($) { my $msg = $_[0]; print "Error==> $msg"; exit; } # End of the handle_error() routine.