#! perl -slw use strict; use threads ( stack_size => 4096 ); use threads::shared; use Thread::Queue; $|++; our $VERBOSE :shared; our $REMOTE :shared; my $stop :shared = 0; ## Set true to terminate threads my @logs = map glob, @ARGV; ## expand wildcards my $Q = new Thread::Queue; ## One trhead per log file threads->create( \&tail, $Q, $_, 1 )->detach for @logs; my $remote; ## Remote watcher socket if( $REMOTE ) { require IO::Socket; $remote = IO::Socket::INET->new( $REMOTE ) or warn "Couldn't connect to $REMOTE : $!, $^E"; print $remote "Hi there, Got your ears on?"; } ## Thread to monitor the Q, print locally and/or forward to remote my $relay = async { for( 1 .. @logs ) { ## Waits for all tals to terminate while( my $line = $Q->dequeue ){ chomp $line; print $line if $VERBOSE; print $remote $line if $remote; } } }; ## Local command loop while( ) { my( $command, $value ) = split; if( $command =~ m[^(END|QUIT)]i ) { $stop = 1; warn "Quiting...\n"; $relay->join; exit 0; } if( $command =~ m[^VERBOSE]i ) { $VERBOSE = $value; print "VERBOSE set to $value"; } elsif( $command eq 'qs' ) { print $Q->pending; } else { print "Unrecognised command: $command"; } } ## Tail threads sub tail { print threads->tid, ' : ', threads->self->get_stack_size; my( $Q, $path, $seconds ) = @_; $seconds = 1 unless $seconds; my $pid = open my $log, "tail -Fs $seconds $path |" or die $@; printf "Thread %d Following $path\n", threads->tid; $Q->enqueue( $_ ) while not $stop and defined( $_ = <$log> ); kill 3, $pid; close $log; $Q->enqueue( undef ); }