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

I am currently trying to scan a log file on my server. I want to match my regex to my file name. This is the error I am getting.

Error opening D:\ServerTools\Logs\ServerLog\((\d+)-(\d+)-(\d+)@(\d+)-( +\d+)\.log ): Invalid argument at script.pl line 109

Here is my actual script

#!/usr/bin/perl -w use DBI; use File::Tail; our $bWin; BEGIN { $bWin = ($^O eq "MSWin32") ? 1 : 0; } &Loop; sub Loop { print "Updating Server Log -> DB\n"; &Update_DB_Actions; } sub Update_DB_Actions { my $dbh = DBI->connect('DBI:mysql:database=arma3;host=localhost',' +root','root') || die "Could not connect to database: $DBI::errstr"; my $filename = q{ServerLog\((\d+)-(\d+)-(\d+)@(\d+)-(\d+)\.log +)}; # my ($sec,$min,$hour,$day,$month,$year) = (localtime)[0,1,2,3,4,5 +]; # my $filename = sprintf("ServerLog(%02d-%02d-%04d).log",$month+1, +$day,$year+1900); my $log = "D:\\ServerTools\\Logs\\$filename"; my $qu_re1 = q{(.?) started server @ (\d+):(\d+):(\d+)}; my $qu_re2 = q{(.?) restarted server @ (\d+):(\d+):(\d+)}; my $qu_re3 = q{(.?) stopped server @ (\d+):(\d+):(\d+)}; $file = File::Tail->new($log); while (defined($line=$file->read)) { my $sql = "INSERT INTO `actions` (log) VALUES (?)"; $insa = $dbh->prepare($sql) or die $!; $insa->execute($line); print "Inserted Action!\n"; } &Loop; }

Also I want to add a way to delete the log file after it is uploaded to the db. Any suggestions?

Replies are listed 'Best First'.
Re: Help w/ regex in filename
by davido (Cardinal) on Jul 06, 2013 at 04:02 UTC

    The simple answer is that you're not invoking File::Tail's new constructor properly. From the POD: "If it has only one paramter, it is assumed to be the filename. If the open fails, the module performs a croak."

    You're asking File::Tail to open a file named, "D:\ServerTools\Logs\ServerLog\((\d+)-(\d+)-(\d+)@(\d+)-(\d+)\.log". That's a very unlikely file name. It looks more like a regexp appended to a path.


    Dave

      Ok heres what I updated it to.

      #!/usr/bin/perl use DBI; use File::Tail; use POSIX(); our $bWin; BEGIN { $bWin = ($^O eq "MSWin32") ? 1 : 0; } Loop(); sub Loop { print "Updating Server Log -> DB\n"; Update_DB_Actions(); } sub Update_DB_Actions { my $dbh = DBI->connect('DBI:mysql:database=arma3;host=localhost',' +root','root') || die "Could not connect to database: $DBI::errstr"; my $filename = POSIX::strftime('ServerLog(%m-%d-%Y).log', localtim +e ); my $log = "D:\\ServerTools\\Logs\\$filename"; my $qu_re1 = q{(.?) started server @ (\d+):(\d+):(\d+)}; my $qu_re2 = q{(.?) restarted server @ (\d+):(\d+):(\d+)}; my $qu_re3 = q{(.?) stopped server @ (\d+):(\d+):(\d+)}; my $file = File::Tail->new(name=>$log); while(defined($line=$log->read)) { my $sql = "INSERT INTO `actions` (log) VALUES (?)"; $insa = $dbh->prepare($sql) or die $!; if($line =~ /$qu_re1/i || /$qu_re2/i || /$qu_re3/i) { $insa->execute($line); print "Inserted Action!\n"; } } unlink $log; }

      But now I get a new error.

      Can't locate object method "read" via package "D:\ServerTools\Logs\Ser +verLog(07- 06-2013).log" (perhaps you forgot to load "D:\ServerTools\Logs\ServerL +og(07-06-2 013).log"?) at script.pl line 112.

        Your File::Tail object is referred to using $file. The variable $log probably doesn't refer to a File::Tail object. use strict 'vars'; would probably catch also catch that $line hasn't been pre-declared, unless you're declaring $line at a broader scope and not showing us.

        Updated to reflect that it's $log that is being misused, not $line.


        Dave

        my $log = "D:\\ServerTools\\Logs\\ $filename";
        my $file = File::Tail->new(name=> $log );
        while(defined($line= $log->read)) {

        Well, $log is a filename (a string), $file is a File::Tail object, but you try to read from $log

        Maybe you want

        $filename = "$directory\\$filename"; my $log = File::Tail->new( name=> $filename );

        Its easier to keep track of what each variable represents if you use meaningful variable names

        $log_filename , $log_filetail, $logreader, $coffebreak

Re: Help w/ regex in filename
by kcott (Archbishop) on Jul 06, 2013 at 04:54 UTC

    G'day dcthehole,

    Welcome to the monastery.

    You give your error as being "at script.pl line 109" and then you write "Here is my actual script" which is followed by substantially less than 109 lines of code. So, either you've posted something other than script.pl or you've removed dozens of lines from it (probably near the beginning). Given that, the following is very much guesswork.

    This line

    my $filename = q{ServerLog\((\d+)-(\d+)-(\d+)@(\d+)-(\d+)\.log)};

    looks like you're trying to generate a filename using data you've captured in a regexp; however, you're not even close with that syntax: you appear to have embedded the pattern in a literal string. Alternatively, you may be attempting to assemble a regexp but you don't show any code doing that. Take a look at perlretut - Perl regular expressions tutorial.

    You have similar code when assigning to $qu_re1, $qu_re2 and $qu_re3. You don't show any use for those variables: I don't know why they're there or what they're supposed to do.

    You should probably be calling your subroutines like sub_name() instead of &sub_name; however, maybe the missing code would reveal why you're doing it this way. Take a look at perlsub - Perl subroutines.

    You'd do well to use strict at the start of your code. It's also preferable to use warnings instead of the -w switch (see perlrun).

    If you need to ask follow-up questions, please follow the guidelines in "How do I post a question effectively?": you'll get a much better answer rather than guesses.

    -- Ken

      The flip side of the coin is that 109+ lines of code aren't really needed to reproduce the error. Ideally the code producing the error would be reduced to 5-25 lines of code, and the error message would be a copy/paste of what that 5-25 LOC example produces. Often while going through the exercise of narrowing the problem down to a brief snippet of code that can still reproduce the problem, one discovers what the problem is, eliminating the reason to ask.


      Dave

        Yes, I absolutely agree and that's why I included the link to "How do I post a question effectively?" (for any follow-up questions) as it recommends posting:

        "... a minimal script that reproduces your problem ..." [original emphasis]

        The main thrust of my first paragraph was to highlight the fact that the error message didn't marry up with the posted code and my following comments were very much guesses.

        I have just noticed that the second version of the OP's code (Re^2: Help w/ regex in filename) has about 40 lines but the error message shows "at script.pl line 112". There's clearly something else going on there that we're not privy to: maybe that's script.pl and the OP is removing part of it; maybe script.pl is a completely different piece of code that's requiring the posted code; maybe it's neither of those.

        -- Ken

        I just have alot of code commented out. Thats why it is at 109+ lines. I havent found anything in those links to help me fix this problem.
Re: Help w/ regex in filename
by Athanasius (Archbishop) on Jul 06, 2013 at 04:13 UTC

    Hello dcthehole, and welcome to the Monastery!

    Some additional observations:

    1. You should always use strict.
    2. Subroutines should be called like this: Loop() rather than like this: &Loop (unless you have a good reason to disable prototypes).
    3. Module File::Tail does not install on Windows. You carefully set $bWin but then don’t use it when initialising $file.
    4. Subroutine Loop calls Updata_DB_Actions, then Update_DB_Actions calls Loop. This is a recipe for infinite recursion.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Thank you for that additional info. And I was using the loops to cause the recursion purposefully. And as for the File::Tail module I downloaded a patch by Steffen Mueller that was created for windows 5 years ago.

Re: Help w/ regex in filename
by Anonymous Monk on Jul 06, 2013 at 03:58 UTC

    If I were you I would try

    use POSIX(); my $filename = POSIX::strftime('ServerLog(%Y-%m-%d).log', localtime );
    and spend some time reading perlintro

    Good luck