Below is the code block that i am currently having issues with.
some background, I am writing a script that will check our network configs, backed up via rancid, for a set of default/need configuration, and outputting any errors to an email.
It works by reading in a file (file name stored as $configs), i then use regex expresions to check for the existence/non existence of a line of config.
The bellow code block should do the following.
OPen the file handle, then whilst the file is open, locate any lines between the following two pieces of Regex interface GigabitEthernet[1-9]/[0-48] and !
It should then check the lines between the two regex for the existence of the lines
logging event link-status
logging event spanning-tree status
spanning-tree portfast
spanning-tree bpduguard enable
If any of the above lines are not between the two regex d eliminators, then it should push the corresponding error message into the array for processing and eventual emailing later.
Whilst the code block below seems to work (sortof) I end up with duplicate entries, which im sure has something to do with the push statements being inside the while statement..
Normally i would do something like this
while (<FH>){
if (/(interface GigabitEthernet[1-9]\/[0-48])/../!/){
$text = $1;
if ($_ !~ /logging event link-status/){
$loggingconfigured++
}
}
if ($loggingconfigured++ == 0) {
push (@PortChecksIOS, "$configs port $text does not have logging event link-status set<br>")
}
But I lose the ability to use $text has it becomes unset outside the while loop.
Below is the code block as it currently stands, any suggestions are welcomed. But please go easy im new to this perl stuff….
sub processPortChecksIOS{
local ($fulldir, $configs, @PortChecksIOS) = @_;
open FH, "$fulldir/$configs" or die $!;
while (<FH>){
if (/(interface GigabitEthernet[1-9]\/[0-48])/../!/){
$text = $1;
if ($_ =~ /switchport mode access/ && $_ !~ /shutdown/){
if ($_ !~ /logging event link-status/){
push (@PortChecksIOS, "$configs port $text does not have logging event link-status set<br>")
}
if ($_ !~ /logging event spanning-tree status/) {
push (@PortChecksIOS, "$configs port $text does not have logging event spanning-tree status set<br>")
}
if ($_ !~ /spanning-tree portfast/){
push (@PortChecksIOS, "$configs port $text does not have spanning-tree portfast set<br>")
}
if ($_ !~ /spanning-tree bpduguard enable/){
push (@PortChecksIOS, "$configs port $text does not have spanning-tree bdpuguard enable set<br>")
}
}
}
}
return @PortChecksIOS;
}
Sample input sw-a-x.x – input file
interface GigabitEthernet1/0/1
description ftp5
switchport access vlan 51
switchport mode access
load-interval 30
spanning-tree portfast
!
interface GigabitEthernet1/0/2
switchport access vlan 51
switchport mode access
load-interval 30
spanning-tree portfast
!
sw-a-z.z – input file
interface GigabitEthernet1/0/1
description ftp5
switchport access vlan 51
switchport mode access
load-interval 30
spanning-tree portfast
logging event link-status
spanning-tree status
spanning-tree bpduguard enable
!
interface GigabitEthernet1/0/2
switchport access vlan 51
switchport mode access
load-interval 30
spanning-tree portfast
!
expected output
sw-a-x.x interface GigabitEthernet1/0/1 does not have logging event link-status set
sw-a-x.x interface GigabitEthernet1/0/1 does not have logging event spanning-tree status
sw-a-x.x interface GigabitEthernet1/0/1 does not have spanning-tree bdpuguard enable set
sw-a-x.x interface GigabitEthernet1/0/2 does not have logging event link-status set
sw-a-x.x interface GigabitEthernet1/0/2 does not have logging event spanning-tree status
sw-a-x.x interface GigabitEthernet1/0/2 does not have spanning-tree bdpuguard enable set
sw-a-z.z interface GigabitEthernet1/0/2 does not have logging event link-status set
sw-a-z.z interface GigabitEthernet1/0/2 does not have logging event spanning-tree status
sw-a-z.z interface GigabitEthernet1/0/2 does not have spanning-tree bdpuguard enable set
First, always use the
strictandwarningspragmas at the top of your code.Second, always use the three argument version of
open, never the two argument version , and use lexical filehandles:Third,
localdoes not do what you think it does, usemyto create variables that exist in the current scope.Fourth, do you really want to match
0,1,2,3,4, or8in that second character class, or do you want to match the integers0through48? If you want the later, you need to sayI would probably write your code like this: