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

I am just looking for some advice on this script, it does work beautifully, but I know there is probably a better way to get this done without as much hassel and probably faster speed in which it completes. To have you understand a bit I will tell you what happened when creating it, so you know why I did this the way I did.

The other day I came here and asked a few people (I am bad with names I am soooooo sorry, but you know who you are and I really really appreciated the help!!) to help me with a problem I had in perl.

I needed to go to over 200 machines, some are WinNT and some are WinXP, and scan the UpdateLog.txt file from McAfee to tell wheather it had been updated or not. If you dont know, NT and XP have different file structures on where they keep this file for McAfee by default. NT uses C:\WINNT\profiles\All Users... and XP uses C:\Documents and Settings\All Users...

I thought the best way would have been to check for what system had what OS and then go from there, but after a bit more thought I remembered that a few of these systems had been upgraded to XP from NT and not a fresh install so they had the NT filesystem intact and no Documents and Settings (sounded wierd to me and still seems wierd).

So instead of checking for the OS I decided my course of action (Mainly because I still suck at Perl) would be to just check if the system had the UpdateLog.txt in C:\WINNT\profiles\All Users... and if it did, it would set the $fname to use the NT file structure and if it did not it would set $fname to use the XP file structure. It then checks for how many days ago the file was modified (found that bit of code on the net).

Here is the code:
#!/usr/bin/perl use strict; use warnings; my $fname; my $name; my $ntfile; my $isfile; use file::find; print "Backing up old timesNT.txt... \n"; rename ("timesNT.txt", "bac/timesNT.bac") || die "Cannot rename timesN +T.txt: $!"; open (NODELIST, "nodelistNT.txt") or die "I could not get at nodelist. +txt as input"; open (TIMES, ">>timesNT.txt") or die "I could not open times.txt as ou +tput"; my $time = localtime(time()); print TIMES "$time.--------------------------------------- +------------------------\n\n"; while (<NODELIST>) { chomp; $name=$_; print "$name \n"; $ntfile = "\"\\\\$name\\c\$\\WINNT\\Profiles\\All Users\\Appli +cation Data\\Network Associates\\VirusScan\\UpdateLog.txt\""; # print "$ntfile\n"; $isfile = ""; $isfile = `dir /B $ntfile`; # print "$isfile\n"; if ($isfile ne "") { $fname = "//$name/c\$/WINNT/Profiles/All Users/App +lication Data/Network Associates/VirusScan/UpdateLog.txt"; print "This system is NT!!!!!!\n"; STUFF(); } else { $fname = "//$name/c\$/Documents and Settings/All U +sers/Application Data/Network Associates/VirusScan/UpdateLog.txt"; print "This system is XP!!!!!!!!!!!!!!!!!\n"; STUFF(); } } close NODELIST; close TIMES; sub STUFF { my $modded = -M $fname; # print TIMES "Server Name: $name\n"; # print TIMES "$modded\n\n"; if ($modded >= 2) { print TIMES "Server Name: $name\n"; print TIMES "$modded\n\n"; } }

Please let me know what you think, is there an easier way to get done what I have?

Replies are listed 'Best First'.
Re: Has McAfee UpdateLog.txt been updated recently
by NetWallah (Canon) on Dec 22, 2006 at 01:01 UTC
    Hae you considered alternative ways to get the information you seek: Update:
    Port 8081 confirmed. Here is what browsing to http://localhost:8081/ reveals:
    McAfee Agent Activity Log Version [3.6.0.453] Computer name [<Computername>] ePO server [<server +name>] View debug logs: FrameSvc current / previous, NaPrdMgr current / previ +ous ------------------------------------------- Date and Time Type Component Message ----------------------------------------------- Sunday, December 17, 2006 2:51:44 PM Info Agent Agent communication + session closed Sunday, December 17, 2006 2:51:44 PM Info Agent Agent communication + session started Sunday, December 17, 2006 2:51:44 PM Info Agent Agent is sending EV +ENT package to ePO server Sunday, December 17, 2006 2:51:44 PM Info Agent Agent is connecting + to ePO server Sunday, December 17, 2006 2:51:44 PM Info Internet Manager Upload s +uccess and no package to receive Sunday, December 17, 2006 2:51:44 PM Info Agent No package received + from ePO Server Sunday, December 17, 2006 2:51:44 PM Info Agent Agent communication + session closed ...

         "A closed mouth gathers no feet." --Unknown

      I have to second the ePO suggestion. I am guessing you are running enterprise mcafee? If you have a support contract, deploy ePO. I used Perl scripts to monitor my AV setup. However, I found that since we were paying for a licenses, why not use it since it comes with the package?

      Some things to consider: 200 less WAN calls for updates to the DATs. Forced updates. Forced Scans. The biggest gift, you can keep your people from uninstalling or hamstringing the AV.

      Now, if you don't have ePO access, you might consider the TieRegistry module. I found there were certain areas of the registry is where mcafee stores DAT info, etc.

      Since you can access the registries remotely, I found that better then hoping shares and trying to open files.

      I should try and find my old level report and see about posting it in the code libraries.

Re: Has McAfee UpdateLog.txt been updated recently
by GrandFather (Saint) on Dec 22, 2006 at 00:31 UTC

    A few coding tips:

    1. Put all your use statements at the top of the file - they are global anyway
    2. Eschew global variable - declare fname, $name ... where they are first used
    3. use consistent indentation that reflects block nesting
    4. Pass parameters to subs rather than relying on global variables - it's easier to see where things are used and where they come from.
    5. multiple ! are a sign of a sick mind ;)

    DWIM is Perl's answer to Gödel

      "Put all your use statements at the top of the file - they are global anyway"
      I deleted the use file::find as I am not usig it in the script it was left over from a previous attempt at somehting I did nto quite understand. :)

      "Eschew global variable - declare fname, $name ... where they are first used"
      When I do this I get an error "Use of uninitialized value in -M at G:\RemoteRegChecks\McAfee Update Check\Nonam e1NT.pl line 45, <NODELIST> line 14.
      Use of uninitialized value in numeric ge (>=) at G:\RemoteRegChecks\McAfee Updat e Check\Noname1NT.pl line 49, <NODELIST> line 14.
      But when I put the declaration at the top of the script I do not have the problem.

      "use consistent indentation that reflects block nesting"
      I am working my best at this for teh life of me I can never please anyone on this, need to take some classes LOL

      "Pass parameters to subs rather than relying on global variables - it's easier to see where things are used and where they come from."
      Would you be able ot elaborate on thsi for me? not quite sure what you mean, in the meantime I will be doing some internet searching for tutorials that mention it. :D

      "multiple ! are a sign of a sick mind ;)"
      How did you know!!!!????? LOL This is mainly there during my testing phase, it prints that out to the command prompt so I could see that part is working :) I will take it out so I do not look as sick anymore (but that does nto mean I am any less sick in the head :) )

      Thank you so far for what you have said, it has me looking at the script more on the formatting side of things to try and get it to look better as well as looking for what is going on with the passing parameters thing (I am wondering if that is what is causing me to get teh errors when I try to declare $fname and $name on first use).

        My (untested) reworked version of your code is:

        #!/usr/bin/perl use strict; use warnings; print "Backing up old timesNT.txt... \n"; rename ("timesNT.txt", "bac/timesNT.bac") || die "Cannot rename timesN +T.txt: $!"; open (NODELIST, "nodelistNT.txt") or die "I could not get at nodelist. +txt as input"; open (TIMES, ">>timesNT.txt") or die "I could not open times.txt as ou +tput"; my $time = localtime(time()); print TIMES "$time.--------------------------------------------------- +------------\n\n"; while (<NODELIST>) { chomp; my $name = $_; print "$name \n"; my $ntfile = "\"\\\\$name\\c\$\\WINNT\\Profiles\\All Users\\Applic +ation Data\\Network Associates\\VirusScan\\UpdateLog.txt\""; my $isfile = `dir /B $ntfile`; if ($isfile ne "") { my $fname = "//$name/c\$/WINNT/Profiles/All Users/Application +Data/Network Associates/VirusScan/UpdateLog.txt"; print "${name}'s system is NT!\n"; STUFF ($name, $fname); } else { my $fname = "//$name/c\$/Documents and Settings/All Users/Appl +ication Data/Network Associates/VirusScan/UpdateLog.txt"; print "${name}'s system is XP!\n"; STUFF ($name, $fname); } } close NODELIST; close TIMES; sub STUFF { my ($name, $fname) = @_; my $modded = -M $fname; return if $modded < 2; print TIMES "Server Name: $name\n"; print TIMES "$modded\n\n"; }

        Note that "Eschew globals" and "Pass parameters" are related.

        I was going to add something about removing cruft - removing the redundant use is good. I notice however that you used lowercase for the module name. You absolutly must use the correct case! Especially on Windows, which is case insensitive for file name, nasty and confusing things happen if the module case is not correct.

        If you want to generate consistent formatting you might want to take a look at Perl::Tidy.


        DWIM is Perl's answer to Gödel