shroh has asked for the wisdom of the Perl Monks concerning the following question:

hi Perl Experts, i am getting the compilation error while executing the script . Below is the code and errors that i am getting.
#!C:\Perl\bin\perl.exe use strict; use warnings; # # This script is created to put the servers # in unplanned outage as part of the tasks that # are received to stop the monitoring on the servers # due to some maintenance activity on the servers. # Author : ROHIT SHARMA (INYROHS) my $path = 'E:/scripts/OutageNodes/'; require $path.'omwNodeDetails.pm'; &main(); sub main { my ($mode,@nodes); $mode=&get_mode(); @nodes=&get_node(); if( $mode eq 'enable'){ &enable_unplanned_outage(@nodes); } elsif($mode eq 'disable'){ &disable_unplanned_outage(@nodes); } else { &printLog("Error invalid Mode $mode");} # clear serverlist printLog ("Truncating serverlist"); open( SRV,'>',$path.'serverlist.txt') or die "Can't open SRV '$path.serverlist': $!"; close SRV; } sub get_mode { # expect values 'enable|disable' my $maintMode = lc $ARGV[0]; chomp($maintMode); if ($maintMode ne "enable") && ($maintMode ne "disable"){ $maintMode="error"; } return ($mainMode); } sub get_node { my ($sPath,$sFile,$sInfile,$sText, @sContent,@serverlist); $sPath="e:/scripts/Outage_nodes"; $sInFile=$sPath.'serverlist.txt'; ##checks if the file exists and pulls the info out if (-e "$sInFile"){ open(INFILE, "<$sInfile") or die "Can't open INFILE + '$sInfile': $!"; while (<INFILE>){ chomp; $sText="$_"; push(@sContent, $sText); } + close INFILE; }else{ &printLog("Error Cannot open $sInFile"); } # check serverlist had entries if (@sContent == 0){ printLog("ERROR No nodes found in $serverlist"); exit; } #get FQDN************ for my $NODE (@sContent){ my ($hostname) = split /\./, $NODE; my $fqdn = getNodeAttributes($hostname,'PrimaryNodeName'); if(length($fqdn) < 1) { printLog("No value returned from WMI, node ($NODE) doesn't ex +its in OMW."); next; } push(@serverlist,$fqdn); return(@serverlist); } sub enable_unplanned_outage { my ($FQDN,$mode,$cmd,@serverlist,$output); @sContent=@_[0..$#_]; foreach $FQDN (@sContent) { $cmd = "ovownodeutil.cmd -outage_node -unplanned -disable_heartb +eat -delete_msgs -node_name $FQDN -on "; printLog("Putting the server $FQDN into outage"); `$cmd`; printLog(`cmd`); } } sub disable_unplanned_outage { my ($FQDN, $mode, $cmd, $cmdresopcmona, @sContent,$output); @sContent = @_[0..$#_]; ####When the servers is brough out of maintenance the agent has to be +recycled to reset all the monitors. foreach $FQDN (@sContent) { $cmd = "ovownodeutil.cmd -outage_node -unplanned -disable_hear +tbeat -delete_msgs -node_name $FQDN -off "; printLog("Node $FQDN >>> off"); $cmdresopcmona = "ovdeploy -cmd \"ovc -restart opcmona\" -host $FQ +DN"; $output=`$cmd`; printLog($cmd); `$cmd`; printLog($output); printLog($cmdresopcmona); `$cmdresopcmona`; } } sub prinLog { my ($sPath, $logFile, $sOutFile, $sText, $date_time, $SEC, $MIN, +$HOUR, $DAY, $MON, $YEAR,$now); #get date/time $SEC, $MIN, $HOUR, $DAY, $MON, $YEAR = (localtime) [0..6]; $date_time = $YEAR + 1900 . $MON + 1 . $DAY . " " . $HOUR . ": +" . $MIN . ":" . $SEC; #get log file parameters $sPath = "e:\\scripts\\outage_nodes"; #review - + change to a standard location $logFile=$sPath."maintenanceMode_$date.log"; my ($logLine) = @_; my $now = sprintf "%02d:%02d:%02d",(localtime)[2,1,0]; open (LOG,'>>',$logfile) or die "Can't open LOG '$logfile': $! +\n"; print LOG "$now $logLine\n"; close LOG; }
And the errors are
E:\scripts\OutageNodes>perl outage_nodes.pl enable "my" variable $sPath masks earlier declaration in same statement at ou +tage_nodes .pl line 80. "my" variable $sPath masks earlier declaration in same scope at outage +_nodes.pl line 82. "my" variable $sText masks earlier declaration in same scope at outage +_nodes.pl line 95. "my" variable $now masks earlier declaration in same scope at outage_n +odes.pl li ne 212. syntax error at outage_nodes.pl line 62, near ") &&" Global symbol "$maintMode" requires explicit package name at outage_no +des.pl lin e 69. syntax error at outage_nodes.pl line 72, near "}" Missing right curly or square bracket at outage_nodes.pl line 231, at +end of lin e Execution of outage_nodes.pl aborted due to compilation errors.

Replies are listed 'Best First'.
Re: Compilation error in the perl script
by stevieb (Canon) on Aug 03, 2015 at 22:03 UTC

    Right off the bat, you've got a missing closing brace } somewhere in the code, that is likely triggering many of the other errors.

    I started trying to sort it out, but your code is so poorly indented it is difficult, but appears you aren't closing this for loop: for my $NODE (@sContent){.

    Get in the habit of indenting your code properly, otherwise these types of issues can be hard to track down. Indent once for each block:

    sub this { for (@this){ print "this\n"; if ($thing){ print $thing; } } }

    Also, don't define your variables at the top of each sub like that... Declare them right before or as they are used, especially in a for loop:

    foreach my $FQDN (...){

    Cleaning up your code layout will allow you to spot issues with closing braces much more readily, and that alone will allow you to sort out the other issues one at a time, and visually see which scope everything is supposed to and is in.

    Also, you have a lot of erroneous whitespace... sometimes items after commas have a space, sometimes not. You use brackets inconsistently as well. Putting a & before a function call isn't required. It's legacy, and currently is only needed in certain circumstances, none of which you're using. Using a consistent style helps tremendously.

    -stevieb

      What is the best way to indent the code, I always create the code in a notepad or a wordpad file which never lets me indent the code. Is there a utility to indent it?
        You can try perltidy, but if you really want to program, you should learn to use a real editor, which can help you with indentation, commenting, completion, etc.
        لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

        I normally recommend vim, but it has quite a large learning curve. I think Notepad++ has decent syntax highlighting and code continuation, but I don't remember for certain (I use Unix).

        Notepad can indent, but not automatically. Typical indenting is one tab per block. However, the standard indenting if possible in your editor is set your tab to four spaces. Here's an article on how to set Notepad++ to 4-space tabs.

        There's perltidy. But you'll probably have to fix the syntax error in your code before it'll work.
        Textpad allows indentation and language specific formatting. This program costs a few bucks, but it works.
      Hi Stevieb, I corrected the errors but when i am trying to execute the script its giving me the error: E:\scripts\OutageNodes>perl outage_nodes.pl disable Can't open LOG 'e:\scripts\OutageNodes\maintenanceMode_201584 14:45:16.log': Inv alid argument Below is my updated code:
      #!C:\Perl\bin\perl.exe use strict; use warnings; #use diagnostics; # # This script is created to put the servers # in unplanned outage as part of the tasks that # are received to stop the monitoring on the servers # due to some maintenance activity on the servers. # Author : ROHIT SHARMA (INYROHS) my $path = 'E:/scripts/OutageNodes/'; require $path.'omwNodeDetails.pm'; &main(); sub main { #my ($mode,@nodes); my $mode=get_mode(); my @nodes=get_node(); if( $mode eq 'enable'){ enable_unplanned_outage(@nodes); } elsif($mode eq 'disable'){ disable_unplanned_outage(@nodes); } else { printLog("Error invalid Mode $mode"); } # clear serverlist printLog ("Truncating serverlist"); open( SRV,'>',$path.'serverlist.txt') or die "Can't open SRV '$path.serverlist': $!"; close SRV; } sub get_mode { # expect values 'enable|disable' my $maintMode = lc $ARGV[0]; chomp($maintMode); if ($maintMode ne 'enable' && $maintMode ne 'disable'){ $maintMode="error"; } return $maintMode; } sub get_node { #my ($sPath,$sFile,$sInFile,$sText, @sContent,@serverlist,$hostname,$f +qdn); my $sPath='e:/scripts/OutageNodes/'; my $sInFile=$sPath.'serverlist.txt'; my @sContent=(); my $sText; ##checks if the file exists and pulls the info out if (-e "$sInFile"){ open(INFILE, "<$sInFile"); while (<INFILE>){ chomp; $sText="$_"; push(@sContent, $sText); } + close INFILE; } else{ &printLog("Error Cannot open $sInFile"); } # check serverlist had entries #if (@sContent == 0){ #printLog("ERROR No nodes found in @serverlist"); # exit; #} #get FQDN************ my $hostname; my $fqdn; my @serverlist; foreach my $NODE (@sContent){ $hostname = split /\./, $NODE; $fqdn = getNodeAttributes($hostname,'PrimaryNodeName'); if(length($fqdn) < 1) { printLog("No value returned from WMI, node ($NODE) doesn't ex +its in OMW."); next; } push(@serverlist,$fqdn); } return(@serverlist); } sub enable_unplanned_outage { #my ($FQDN,$cmd); my @nodelist=@_[0..$#_]; foreach my $FQDN (@nodelist) { my $cmd = "ovownodeutil.cmd -outage_node -unplanned -disable_he +artbeat -delete_msgs -node_name $FQDN -on "; printLog("Putting the server $FQDN into outage"); `$cmd`; printLog(`cmd`); } } sub disable_unplanned_outage { #my ($FQDN, $mode, $cmd, $cmdresopcmona, @sContent,$output); my @sContent = @_[0..$#_]; ####When the servers is brough out of maintenance the agent has to be +recycled to reset all the monitors. foreach my $FQDN (@sContent) { my $cmd = "ovownodeutil.cmd -outage_node -unplanned -disable_h +eartbeat -delete_msgs -node_name $FQDN -off "; printLog("Node $FQDN >>> off"); my $cmdresopcmona = "ovdeploy -cmd \"ovc -restart opcmona\" -host +$FQDN"; my $output=`$cmd`; printLog($cmd); `$cmd`; printLog($output); printLog($cmdresopcmona); `$cmdresopcmona`; } } sub printLog { #my ($sPath, $logFile, $sOutFile, $sText, $date_time, $SEC, $MIN, $ +HOUR, $DAY, $MON, $YEAR,$now,$logLine,$now); #get date/time my($SEC, $MIN, $HOUR, $DAY, $MON, $YEAR) = (localtime) [0..6]; my $date_time = $YEAR + 1900 . $MON + 1 . $DAY . " " . $HOUR . " +:" . $MIN . ":" . $SEC; #get log file parameters my $sPath = "e:\\scripts\\OutageNodes\\"; #revi +ew - change to a standard location my $logFile=$sPath."maintenanceMode_$date_time.log"; my ($logLine) = @_; my $now = sprintf "%02d:%02d:%02d",(localtime)[2,1,0]; open (LOG,'>>',$logFile) or die "Can't open LOG '$logFile': $! +\n"; print LOG "$now $logLine\n"; close LOG; }
Re: Compilation error in the perl script
by 1nickt (Canon) on Aug 03, 2015 at 22:48 UTC

    You also repeatedly call printLog() but your sub is named prinLog.

    The way forward always starts with a minimal test.
Re: Compilation error in the perl script
by runrig (Abbot) on Aug 03, 2015 at 22:07 UTC
    Start by looking at the syntax error on line 61. Everything above that is a warning due to parens not being correct on line 61.
Re: Compilation error in the perl script
by Laurent_R (Canon) on Aug 04, 2015 at 08:32 UTC
    When you have many compile errors like this, the best guess is often to look at the first error (the first line with an error), i.e. in your case line 62. You'll often find a missing something, the something being often a closing " ' ; ) ) or }. Sometimes, though, you might need to go back a bit earlier than the first line reported in error (especially for a missing closing quote mark).
Re: Compilation error in the perl script
by Perl300 (Friar) on Aug 04, 2015 at 14:45 UTC
    From my little experience, I think all your warnings should be gone if you carefully avoid multiple declaration of lexical variables:

    $sPath

    $sText

    $now

    To say it in general terms, you have declared "my $sPath" more than once in your code and if you declare each of above 3 variables only once, then warnings should be gone.

    For the errors you have already got enough valuable advise.