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

Hi people,

trying to gather information from several logfiles at once, outputting relevant (to me) information to the screen. This mean I have to have an unspecified number of files open for reading at the same time. Unspecified because the config file can contain any number of files to be 'tailed' along with what regexps to match to each file.

I'v tried using a hash like %monitored_files containing data like this:
use strict; my %monitored_files; %monitored_files = ( "messages" => "/var/log/messages" ); my $key; foreach $key (keys (%monitored_files)) { open ($key, $monitored_files{$key}) or die " ! Could not open $key +: $!"; print(" * $key opened\n"); }
Now, I know I can't do this when using strict, but, how else? I want to use strict, but is there no way of constructing the filehandle on the fly so I can predict what the filehandle will be called when using it later? Am I making sense at all?

Since I probably am thinking the wrong way about this problem, would someone please point me the right way?

Thanks!

Replies are listed 'Best First'.
Re: Reading multiple files at the same time
by l2kashe (Deacon) on Dec 08, 2003 at 23:41 UTC

    Or the FileHandle module even
    Update: changed vars to more descriptive names

    #!/usr/bin/perl use strict; use FileHandle; # what to watch my %monitor = ( 'messages' => '/var/adm/messages', ); # how to watch it. my %handles; for ( keys %monitor ) { $handles{ monitor{$_} } = new FileHandle "$monitor{$_}", "r" or die "Cant open $monitor{$_}: $!\n"; } # And use it # WARNING blocking code ahead!! my $sentinel; # how we get out of the while 1 while (1) { last if $sentinel; while ( my($file, $fh) = each %handles ) { chomp(my $line = <$fh>); print "Saw in file: $file\n$line\n\n"; $sentinel++ if $line =~ m/somethingorother/; } }

    Also File::Tail might be of some use along the same lines

    use perl;

Re: Reading multiple files at the same time
by Paladin (Vicar) on Dec 08, 2003 at 22:34 UTC
    You could try using a data structure like the following:
    %monitored_files = ( "messages" => { FILE => "/var/log/messages", HANDLE => undef, } );
    Then use it like:
    foreach $key (keys (%monitored_files)) { open ($monitored_files{$key}{HANDLE}, $monitored_files{$key}{FILE} +) or die "Could not open $key: $!"; print(" * $key opened\n"); }
      Also if you are going to allow any number of files to be opened this way it may be worthwhile setting a limit that is below the normal proccess/user max file descriptor number for your system.


      -Waswas
Re: Reading multiple files at the same time
by waswas-fng (Curate) on Dec 08, 2003 at 22:35 UTC
    Try a FIELHANDLE ref...
    #!/usr/bin/perl -w use strict; open(OUTFILE, ">out.txt") or die "cannot open out.txt: $!"; my $filehnd = {}; $filehnd->{outfile} = \*OUTFILE; print {$filehnd->{outfile}} "This is a test\n";


    -Waswas
Re: Reading multiple files at the same time
by Zaxo (Archbishop) on Dec 09, 2003 at 08:47 UTC

    I think you want to use four-argument select, or else the more housebroken IO::Select. Those can be used to sleep until some file handle from a set you watch is readable.

    After Compline,
    Zaxo