Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 116199
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 11, 20262026-05-11T03:08:25+00:00 2026-05-11T03:08:25+00:00

My question is the antithesis of How do I process input immediately instead of

  • 0

My question is the antithesis of How do I process input immediately instead of waiting for newline. I want to continue reading a growing log file, but stop after the file has not grown for a specified number of seconds.

I found Sys::AlarmCall at CPAN, and tried as shown below, but it doesn’t time-out when I run:

perl progress.tracker.pl progress.tracker.pl 

I’m guessing that this is something to do with the auto-magic associated with the ‘<>‘ operator. But I’m not sure how to go about rewriting the code. I’m OK with an explicit open of just one file (instead of an arbitrary number of files), defaulting to standard input if no file is specified – I only ever expect to use it with one file name.

(The script generates a dot for each line read, generating a newline every 50 lines read, and outputting a timestamp every 25 lines of dots. I use it to track the progress of long-running builds. The current incarnation is fed by tail -f, but that is not exiting when this script does, mainly because it never gets any more input to write to the now non-existent progress tracker. The ‘last’ line stuff is a marker in the log files I normally process; I want to remove it. The timeout will be of the order of minutes, not sub-second.)

#!/usr/perl/v5.10.0/bin/perl -w # # @(#)$Id: progress.tracker.pl,v 1.3 2009/01/09 17:32:45 jleffler Exp jleffler $ # # Track progress of a log-generating process by printing one dot per line read.  use strict; use constant DOTS_PER_LINE => 50; use constant LINES_PER_BREAK => 25; use constant debug => 0; use POSIX qw( strftime ); use Sys::AlarmCall;  sub read_line {     print '-->> read_line()\n' if debug;     my $line = <STDIN>;     printf '<<-- read_line(): %s', (defined $line) ? $line : '\n' if debug;     return $line; }  my $line_no = 0; my $timeout = 30; my $line;  $| = 1;     # Unbuffered output  while ($line = alarm_call($timeout, 'read_line', undef)) {     $line_no++;     print '.';     print '\n' if ($line_no % DOTS_PER_LINE == 0);     printf '%s\n', strftime('%Y-%m-%d %H:%M:%S', localtime(time))         if ($line_no % (DOTS_PER_LINE * LINES_PER_BREAK) == 0);     last if $line =~ m/^Trace run finished: /; }  print '\n'; print $line if defined $line && $line =~ m/^Trace run finished: /; 

Any suggestions? (Preferably apart from ‘get off your **** and code it in C’!)


File::Tail seems to meet my requirements pretty well. The revised code is:

#!/usr/perl/v5.10.0/bin/perl -w # # @(#)$Id: progress.tracker.pl,v 3.2 2009/01/14 07:17:04 jleffler Exp $ # # Track progress of a log-generating process by printing one dot per line read.  use strict; use POSIX qw( strftime ); use File::Tail;  use constant DOTS_PER_LINE   => 50; use constant LINES_PER_BREAK => 25; use constant MAX_TIMEOUTS    => 10; use constant TIMEOUT_LENGTH  => 30; # Seconds  my $timeout    = TIMEOUT_LENGTH; my $line_no    = 0; my $n_timeouts = 0; my $line;  sub print_item {     my($item) = @_;     $line_no++;     print '$item';     print '\n' if ($line_no % DOTS_PER_LINE == 0);     printf '%s\n', strftime('%Y-%m-%d %H:%M:%S', localtime(time))         if ($line_no % (DOTS_PER_LINE * LINES_PER_BREAK) == 0); }  $| = 1;     # Unbuffered output  # The foreach and while loops are cribbed from File::Tail POD. my @files; foreach my $file (@ARGV) {     push(@files, File::Tail->new(name=>'$file', tail => -1, interval => 2)); }  while (1) {     my ($nfound, $timeleft, @pending) = File::Tail::select(undef, undef, undef, $timeout, @files);     unless ($nfound)     {         # timeout - do something else here, if you need to         last if ++$n_timeouts > MAX_TIMEOUTS;         print_item '@';     }     else     {         $n_timeouts = 0;  # New data arriving - reset timeouts         foreach my $tail (@pending)         {             # Read one line of the file             $line = $tail->read;             print_item '.';         }     } }  print '\n'; print $line if defined $line && $line =~ m/^Trace run finished: /; 

There is room for improvement; in particular, the timeouts should be configurable. However, it seems to work as I wanted. More experimentation and tweaking is required.

It seems that the $tail->read() function reads one line at a time; that is not totally obvious from the POD.


Sadly, upon further practical use, it appears that the way I’m using the File::Tail code doesn’t work the way I need it to. In particular, once it stalls on a file, it doesn’t seem to resume again. Rather than spend the time trying to work out what was wrong, I fell back on the alternative – code it myself in C. It took less than 2 hours to get a version with the bells and whistles I wanted added. I’m not sure whether I would have been able to get those into Perl as quickly, quite apart from the debugging of (my use of) File::Tail. One oddity: I set my code to use 4096 byte buffers; I found one line in the build process I monitor is over 5000 bytes long. Ah well – the code still uses 4096 byte buffers, but emits a dot for an over-long line like that. Good enough for my purposes. I also find that I need to allow for 5 minute pauses in the build output.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. 2026-05-11T03:08:25+00:00Added an answer on May 11, 2026 at 3:08 am

    Have you tried File::Tail to handle the actual tailing instead of trying to coerce <STDIN> to do the job?

    Or, if that piece does work, in what way is this failing?

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Ask A Question

Stats

  • Questions 124k
  • Answers 124k
  • Best Answers 0
  • User 1
  • Popular
  • Answers
  • Editorial Team

    How to approach applying for a job at a company ...

    • 7 Answers
  • Editorial Team

    How to handle personal stress caused by utterly incompetent and ...

    • 5 Answers
  • Editorial Team

    What is a programmer’s life like?

    • 5 Answers
  • Editorial Team
    Editorial Team added an answer Are you running on OS 3.0? I saw the same… May 12, 2026 at 1:19 am
  • Editorial Team
    Editorial Team added an answer It looks like you need to register Apache::Session::Memcached with Apache::Session::Wrapper,… May 12, 2026 at 1:19 am
  • Editorial Team
    Editorial Team added an answer Use DATENAME or DATEPART: SELECT DATENAME(dw,GETDATE()) -- Friday SELECT DATEPART(dw,GETDATE())… May 12, 2026 at 1:19 am

Related Questions

My question is the following. I have xml that is versioned by a namespace.
My question is the following: When using software such as Skype, TVU player or
My question is on the ASP.NET GridView control. I am using a CommandField in
My question is related to the command pattern, where we have the following abstraction

Trending Tags

analytics british company computer developers django employee employer english facebook french google interview javascript language life php programmer programs salary

Top Members

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.