in reply to Subroutine to delete one file and copy one file to another

You should be using use strict; and use warnings;, and that would have caught you have a typo in one of your variables ($delTemp) in the unlink().

You should also check if the file exists, and then report back if unlink() failed...

if (-f $delTemp){ unlink $delTemp or die "can't delete >$delTemp< file: $!"; }

To further, you should check the copy() was successful as well:

my $a = 'a.txt'; my $b = 'b.txt'; copy $a, $b or die "can't copy $a to $b: $!"; die "can't find copied file $b: $!" unless -f $b;

-stevieb

Replies are listed 'Best First'.
Re^2: Subroutine to delete one file and copy one file to another
by afoken (Chancellor) on Jul 21, 2015 at 17:00 UTC
    if (-f $delTemp){ unlink $delTemp or die "can't delete >$delTemp< file: $!"; }

    This opens a door for a race condition (https://en.wikipedia.org/wiki/Time_of_check_to_time_of_use): Someone can change the file $delTemp between the stat call inside -f and the unlink call.

    The clean way to handle this: Just call unlink. Yes, unlink will fail when $delTemp does not exist. Check $! before calling die. POSIX specifies that unlink will return ENOENT if and only if the file was not found.

    Something like the following should do the trick, using %! (available since Perl 5.005):

    unlink $delTemp or $!{ENOENT} or die "can't delete '$delTemp': $!";

    See also Re^2: Subroutine to delete one file and copy one file to another.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re^2: Subroutine to delete one file and copy one file to another
by shroh (Acolyte) on Jul 20, 2015 at 20:56 UTC
    Hi , I will show you my complete code , which after using strict and warnings is not getting complied.
    #!C:\Perl\bin\perl.exe use Win32; use IO::Handle; use File::Find; use strict; use warnings; use File::Copy qw(copy); ###################################################################### +############## #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. # # # #expect values 'on|off' ($SEC,$MIN,$HOUR, $DAY, $MON, $YEAR)= (localtime) [0..6]; $year=$YEAR+1900; $month=$MON+1; $day=$DAY; $date="$year\_$month\_$day"; $LOG="E:/Temp/inyrohs/maintenanceMode_$date.log"; my $tempfile="E:/Temp/inyrohs/temp/outagenodes_temp.txt"; my $serverlist="E:/Temp/INYROHS/serverlist.txt"; open( MYFILE, "<E:/Temp/INYROHS/serverlist.txt"); @outagenodes=<MYFILE>; close MYFILE; open ( MYTEMPLIST, "<E:/Temp/INYROHS/temp/outagenodes_temp.txt"); @tempnodes=<MYTEMPLIST>; close MYTEMPLIST; print "@outagenodes\n"; #Below subroutine call is to delete the temp file if already existing +so that the outage is not run on the previously entered servers. deleteTemp($tempfile,$serverlist); open (LOG,">> $LOG") or die "Can't open $LOG file: $!\n"; printf LOG ("\nTime is %02d:%02d:%02d.\nStarting the maintenance mode +process to turn $maintMode outages.\n\n", $HOUR, $MIN, $SEC); print "$date \n"; print "starting the process \n"; my $maintMode=$ARGV[0]; chomp($maintmode); print "maintMode: $maintMode:\n"; foreach $NODES (@tempnodes) { printLog("Node: $NODES, processing...\n"); if($maintMode =~ m/on/) { print "entered loop \n"; $cmd="ovownodeutil -outage_node -unplanned -disable_heartb +eat -delete_msgs -node_name $NODES -$maintMode "; print "$cmd\n"; system($cmd); print "done with command"; } elsif($maintMode=~ m/off/) { printLog("Putting the server $NODES in the outage.\n"); $cmd="ovownodeutil.cmd -outage_node -unplanned -disable_he +artbeat -delete_msgs -node_name $NODES -$maintMode"; #$cmdstopopcmona="ovdeploy -cmd "ovc -stop opcmona" -host +$NODES"; #$cmdstopopcle="ovdeploy -cmd "ovc -start opcle" -host $NO +DES"; #$cmdstartopcmona="ovdeploy -cmd "ovc -start opcmona" -hos +t $NODES"; #$cmdstartopcle="ovdeploy -cmd "ovc -start opcle" -host $N +ODES"; # $cmdstart="opcragt -start $NODES"; print "$cmd\n"; system($cmd); # print "$cmdstopopcmona\n"; # # system($cmdstopopcmona); # # print "$cmdstopopcle"; # system($cmdstopopcle); # print "$cmdstartopcle\n"; # system($cmdstartopcle); # #print "$cmdstart\n"; # system($cmd); # system($start); } } sub printLog { my ($logLine) = @_; chomp($logLine); $logLine=$logLine . "\n"; print "$logLine"; print LOG "$logLine"; } sub deletTemp { my ($delTemp,$serverlist)=@_; print "temp: $delTemp\n"; print "serv: $serverlist\n"; unlink $delTemp; copy($serverlist,$delTemp); }
    And below are the errors:
    E:\Temp\inyrohs>perl outage_nodes.pl on Possible unintended interpolation of @outagenodes in string at outage_ +nodes.pl line 48. Variable "$LOG" is not imported at outage_nodes.pl line 59. Global symbol "$SEC" requires explicit package name at outage_nodes.pl + line 20. Global symbol "$MIN" requires explicit package name at outage_nodes.pl + line 20. Global symbol "$HOUR" requires explicit package name at outage_nodes.p +l line 20. Global symbol "$DAY" requires explicit package name at outage_nodes.pl + line 20. Global symbol "$MON" requires explicit package name at outage_nodes.pl + line 20. Global symbol "$YEAR" requires explicit package name at outage_nodes.p +l line 20. Global symbol "$year" requires explicit package name at outage_nodes.p +l line 22. Global symbol "$YEAR" requires explicit package name at outage_nodes.p +l line 22. Global symbol "$month" requires explicit package name at outage_nodes. +pl line 23. Global symbol "$MON" requires explicit package name at outage_nodes.pl + line 23. Global symbol "$day" requires explicit package name at outage_nodes.pl + line 24. Global symbol "$DAY" requires explicit package name at outage_nodes.pl + line 24. Global symbol "$date" requires explicit package name at outage_nodes.p +l line 25. Global symbol "$year" requires explicit package name at outage_nodes.p +l line 25. Global symbol "$month" requires explicit package name at outage_nodes. +pl line 25. Global symbol "$day" requires explicit package name at outage_nodes.pl + line 25. Global symbol "$LOG" requires explicit package name at outage_nodes.pl + line 27. Global symbol "$date" requires explicit package name at outage_nodes.p +l line 27. Global symbol "@outagenodes" requires explicit package name at outage_ +nodes.pl line 37. Global symbol "@tempnodes" requires explicit package name at outage_no +des.pl line 44. Global symbol "@outagenodes" requires explicit package name at outage_ +nodes.pl line 48. Global symbol "$LOG" requires explicit package name at outage_nodes.pl + line 59. Global symbol "$LOG" requires explicit package name at outage_nodes.pl + line 59. Global symbol "$maintMode" requires explicit package name at outage_no +des.pl line 61. Global symbol "$HOUR" requires explicit package name at outage_nodes.p +l line 61. Global symbol "$MIN" requires explicit package name at outage_nodes.pl + line 61. Global symbol "$SEC" requires explicit package name at outage_nodes.pl + line 61. Global symbol "$date" requires explicit package name at outage_nodes.p +l line 63. Global symbol "$maintmode" requires explicit package name at outage_no +des.pl line 71. Global symbol "$NODES" requires explicit package name at outage_nodes. +pl line 76. Global symbol "@tempnodes" requires explicit package name at outage_no +des.pl line 76. Global symbol "$NODES" requires explicit package name at outage_nodes. +pl line 83. Global symbol "$cmd" requires explicit package name at outage_nodes.pl + line 95. Global symbol "$NODES" requires explicit package name at outage_nodes. +pl line 95. Global symbol "$cmd" requires explicit package name at outage_nodes.pl + line 97. Global symbol "$cmd" requires explicit package name at outage_nodes.pl + line 99. Global symbol "$NODES" requires explicit package name at outage_nodes. +pl line 112. Global symbol "$cmd" requires explicit package name at outage_nodes.pl + line 114. Global symbol "$NODES" requires explicit package name at outage_nodes. +pl line 114. Global symbol "$cmd" requires explicit package name at outage_nodes.pl + line 128. Global symbol "$cmd" requires explicit package name at outage_nodes.pl + line 131. Execution of outage_nodes.pl aborted due to compilation errors.
      Hi shroh,

      You can add 'my' to the variable declarations wherever the error messages indicates.

      Then you will get an appropriate error message about undefined subroutine because 'e' is missing in your sub name.

      ... sub deletTemp { ...

        Right on (in para 2 of pme's Re^3: Subroutine to delete one file and copy one file to another) re the sub,
          ...but uhmm, not so much re:
                "... add 'my' to the variable declarations wherever (emphasis supplied) the error messages indicates."

        Not a good idea: $YEAR gets an error message at lines 20 & 22 (and possibly some others; TL, DR) while $year and several others also have multiple instances.

        In this case, the $YEAR in Ln 22 is supposed to contain or represent the same value as that in Ln 20, so the one at 20 (in fact the whole list of vars there) should get a my.

        But adding a my to the $YEAR in Ln 22 would break the process.

        It may be that some of the vars in OP's code are instances (bad practice) of using the same name in different scopes. Simply iterating thru an edit/test cycle will probably not cure any problem of that character, but it's probable, IMHO, that some variables identified MORE THAN ONCE in the error messages are intended to be global.

        In that case, adding a my before the first open parenthesis on Ln 20 will make many of Perl's help messages (because that's what error messages and warnings are)"go away". Adding a my before the first instance of each var cited in an error message may help OP to find most of the problems in the code shown. But marking all of them with mys will probably break the code and confuse the Seeker even further.


        Precise language is the GodFather of precise code!

        Most of the errors are now resolved after putting the "my" before each variable.
        i have few concerns: 1) If the temp file doesnt exist , i need to create one and copy the c +ontents of serverlist.txt in the newly created temp file. 2) If it already exists, i need to delete the contents of that temp fi +le and copy the contents of server.txt into the existing temp file. How this is possible? Any help is highly appreciated. Thanks
Re^2: Subroutine to delete one file and copy one file to another
by shroh (Acolyte) on Jul 20, 2015 at 22:15 UTC
    Hi Stieve, May be i am stuck up in here: What i want is stated below: 1) If i dont have the temp file, it should create a new file and copy the contents of serverlist(already existing) into the newly created temp file. 2) If the file is already existing, it should delete the temp file and again copy the contents of that file into the temp file. All i want this to be done in the subroutine.

      Without trying the whole of your main program, it looks like the other monks have the delete subroutine correct--so the main program I think is the problem. Speaking for myself, I would start by cleaning up that ugly code and rename some varables variables to help make it clear what I am tring trying to do. Some good comments would help, too.