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

Hi Experts, I am not seeing any compilation errors while running the script but the script is not able to open the log file and giving me the below error: E:\scripts\OutageNodes>perl outage_nodes.pl enable Can't open LOG 'e:\scripts\OutageNodes\maintenanceMode_201586 9:45:1.log': Inval id argument

#!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; }

Replies are listed 'Best First'.
Re: Script is unable to open file
by marinersk (Priest) on Aug 06, 2015 at 17:13 UTC

    While embedded spaces in your filenames are acceptable, you cannot normally have a colon in your filename in Windows. There used to be shennanigans you could use to force them in, but normal usage of opendoes not include this.

    You can fabricate a slightly cleaner filename:

    my $logFile = "C:\\Test\\Data\\Mytime1:00:34 AM"; my ($logDrive, $logFilebase) = split /\:/, $logFile, 2; $logFilebase =~ s/[\:\>\<\|\s]+/\_/g; my $cleanLogFile = "$logDrive\:$logFilebase"; print " \$logFile: [$logFile]\n"; print "\$cleanLogFile: [$cleanLogFile]\n";

    Results:

    D:\PerlMonks>\steve\t\t22.pl $logFile: [C:\Test\Data\Mytime1:00:34 AM] $cleanLogFile: [C:\Test\Data\Mytime1_00_34_AM]

    Update: Definite ++to 1nickt for the use of standard module for date/time consistency, as well as the universal format. You'll still need to filter out or convert the colons.

Re: Script is unable to open file
by 1nickt (Canon) on Aug 06, 2015 at 16:55 UTC

    There's a space in the value of $date_time so your open() call thinks the filename is e:\scripts\OutageNodes\maintenanceMode_201586 and that you are passing 9:45:1.log as another argument. (Update: Problem is the colons, not the space as pointed out by marinersk, I was guessing at the exact cause of the error.)

    Just use DateTime.

    use DateTime; my $dt = DateTime->now; my $file = 'foo_' . $dt; print $file;

    Prints:

    foo_2015-08-06T17:05:17

    Note that this gives the datetime in ISO-standard format, which is good for later use elsewhere. Note also that now() returns a datetime in UTC timezone, so if you want your local time just use

    $dt = DateTime->now( time_zone => 'local' );

    If you can't have colons in the file name, just specify a different format:

    my $dt = DateTime->now(time_zone => 'local')->strftime("%Y-%m-%d-%k-%M +-%S");

    Prints:

    2015-08-06-10-42-18

    Finally note that $dt is a DateTime object but if you use it as a string it prints the datetime so you can be lazy.

    Upate: showed DateTime use
    The way forward always starts with a minimal test.

      The problem isn't the spaces, it's the colons.

Re: Script is unable to open file
by stevieb (Canon) on Aug 06, 2015 at 17:04 UTC

    EDIT: This answer is incorrect for the OP's specific problem as I wasn't doing a full test on the code, and was only using the result. marinersk pointed out the real issue.

    What this points out is the error reporting difference when using strict and not when using a file path in Windows without escaping the path delimiters (\).

    With use strict;

    C:\Users\steve\Desktop>perl log.pl Unrecognized escape \s passed through at log.pl line 4. Unrecognized escape \O passed through at log.pl line 4. Unrecognized escape \m passed through at log.pl line 4. Invalid argument at log.pl line 4.

    Without use strict;

    C:\Users\steve\Desktop>perl log.pl Invalid argument at log.pl line 2.

    See the difference and how it expressly shows you the exact specific problems? To fix this, double up your backslashes in the path:

    "e:\\scripts\\OutageNodes\\maintenanceMode_201586 9:45:1.log"

    -stevieb