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

Hi Everyone, I'm quite new guy in Perl so I need your help;) I wrote some sniffer which will log every packet into log file. So basically every packet is saved into file. I want to switch file every 60 secs, unfortunately I have a problem with that. this checks the time inside the packet_capture subroutine:
if ( time > $NEXT_TIME ) { print "Change file\n"; thread_log(); }
and this is subroutine which should change file
sub thread_log { #closing the handler to the current file if ( -e "log$FILE_NUMBER.log" ) { close($LOG_FILE); } $FILE_NUMBER += 1; open( $LOG_FILE, '>', "log$FILE_NUMBER.log" ) or die "Unable to open l +ogfile:$!\n"; $NEXT_TIME = $NEXT_TIME + 60; }
I know that this code can be written in better way so I'm open to any suggestions. Thanks in advance for any help ;)

Replies are listed 'Best First'.
Re: Problem with switching log files
by Sewi (Friar) on Dec 27, 2011 at 20:58 UTC

    It's hard to find all possible problems without the complete source file, but let's go with the snippets you pasted:

    First of all: Debugging. Never ever think that you know the value of a variable. If something goes wrong - add print or warn statements to your source and look at the values while the script is running. This is the same for Perl gurus and beginners. You already started that by your print "Change file\n";

    Let's only look at $NEXT_TIME. It's not initialized, so it's initial numeric value is 0. This is less than time, so your script is going to change the file the first time it's going to that if at the first line of your pasted source. The file is switched (a new file is opened) and the next timestamp is set to $NEXT_TIME + 60. Remember, $NEXT_TIME was 0 and 0 + 60 = 60. Current time is 1325018738 and your requested next file is due at 60 (which should be something like 1970-01-01 00:01:00). $NEXT_TIME = time + 60 might be better, but it's less accurate because you likely won't reach this line as soon as $NEXT_TIME is reached: You'ld get "60 seconds after setting $NEXT_TIME to the new value" instead of "60 seconds after estimated start time of last file", but this should/might be good enough.

    Add some debug statements to see the value of $LOG_FILE. It will be some kind of reference but the address (hexadecimal number) will show you if a file has been rotated. You should at least check the value right after your open call and just before writing into this filehandle.

    You already added a "or die" error handler to your open call, so if the file isn't cycled and you don't get an error (where your $! should help you to get the right reason), I assume that your code never reaches the sub thread_log for the second time.

    Your sub is called thread_log and I hope that doesn't mean that you're using threads. Don't do this for starting with Perl, threads have some hard-to-handle effects. Get your script running without threads and then add threads if you feel that you need them. If you just used this prefix without any threading stuff, ignore this :-).

    If you could feed only very very very few packets into your logger, install Devel::Trace and start your script using perl -d:Trace my_packet_logger.pl. This will show you any Perl source line as it's processed, but will heavily slow down your script (because screen output is slow). You might also use the Perl debugger but it's not that easy to use for beginners.

    There are some lines that I'ld write another way, but Perl is TIMTOWTDI and it's ok. There are many "bad style" things you didn't use, so your code quality is very good for a beginner (I think).

Re: Problem with switching log files
by RichardK (Parson) on Dec 27, 2011 at 19:18 UTC
    So what's your problem? What isn't working?
      I don't know why is not working ;)

      I had a error: Unable to open logfile:Permission denied

      I'm working as a root so I should have permission to create any file

        I'm working as a root so I should have permission to create any file

        That is simply not true. There are a number of possibilities that can prevent even root to write to a file (or create it):

        • file is readonly
        • directory if readonly
        • filesystem is readonly (for example CDROM)
        • out of filehandles
        • out of memory
        • disk full
        • file system errors that implicitly make the filesystem readonly
        • file locked by another program
        • directory locked by another program (most likely kernel during some directory move operations)
        • file on a network filesystem where you don't have permissions
        • Some "virtual" files can't be written to (/proc/*)
        • ...The list goes on and on and on to ever more obscure "error" conditions...

        BREW /very/strong/coffee HTTP/1.1
        Host: goodmorning.example.com
        
        418 I'm a teapot
        I can open the first log file, but with next file I have a problem:(
Re: Problem with switching log files
by TJPride (Pilgrim) on Dec 27, 2011 at 20:31 UTC
    You should probably print out the path on the line before you try to create the file. Make sure nothing screwy is going on, like the $FILE_NUMBER variable resetting and having you try to open the same file simultaneously on two separate threads (or whatever).
      Thanks guys for your help and hints. Problem was solved. The directory should have permission 777 not 775 :) so simple solution ;)