Perl's buffered I/O is causing me to miss latest log file entries in log colorizer. How to fix?


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Perl's buffered I/O is causing me to miss latest log file entries in log colorizer. How to fix?
# 1  
Old 05-19-2011
Perl's buffered I/O is causing me to miss latest log file entries in log colorizer. How to fix?

I've been finding myself using a log file colorizer written in perl to reformat and colorize the output from many different programs. Mainly, however, I use it to make the output from "tail -f" commands more readable.

The base perl script I use is based on "colorlogs.pl" available from the resentment dot org web site (I would post the URL, but I am but an egg in these forums and hence not worthy ... I can mail or PM it to anyone who is curious). It's a nice little script, and it works well for busy log files. I've extended it a little, but most of it is as originally written.

Unfortunately, on our test system, the logs I'm viewing aren't very busy, and it could be several minutes .. or hours ... between changes in the file.

Because of the very low level of actitivity, I've discovered that the last several lines aren't always displayed (it wasn't obvious on a system with messages coming in every few seconds), and the culprit appears to be the fact that the perl open and print commands perform buffered I/O. This is surely good most of the time, but not in this instance.

Example calling syntax:

Code:
 tail -f somefile | colorlogs.pl

The code is fairly simple ... it has a list of colornames associated with various ANSI control sequences, it reads a config file which associates those colornames with various arbitrary strings to match, and then it reads STDIN to obtain the output text to colorize.

Code:
# Parse STDIN
while ($line=<>) {
    $matched = 0;
    foreach $string (keys %config) {
        if ($line =~ /$string/) {
             $otextcolor=$textcolor;
             $textcolor=$config{$string};
             if (($textcolor eq $scolor1)
             or ($textcolor eq $scolor2)
             or ($textcolor eq $scolor3)) {
                 $matched = 1;
             }
         }
     }
    if (!$matched) {
        print "$colors{default}$line";
    } else {
        if ($textcolor eq "cyan") {
                print "$colors{default}===> Incoming\n$colors{cyan}$line$colors{default}";
        } elsif ($textcolor eq "brightcyan") {
                print "$colors{default}<=== Outgoing\n$colors{brightcyan}$line$colors{default}";
        } elsif ($textcolor eq "cyanza") {
                print "$colors{default}*** Special ***\n$colors{cyan}$line$colors{default}";
        } else {
                print "$colors{$textcolor}$line$colors{default}";
        }
    }
}

I've done some searching, read the "Suffering from Buffering" web site, and tried various things like sticking:

Code:
my $original_fh = select STDOUT;
$| = 1;
select STDERR;
$| = 1;
select $original_fh;

or

Code:
select((select(STDOUT), $|=1)[0]);

in the while loop to make STDOUT a "hot" handle, but that doesn't seem to make any difference. The issue might be STDIN. I dunno. Smilie

I also know that sysread and syswrite are unbuffered statements I could use, but I'm not sure how to adapt the existing code to do that. I'm still a relative Perl newbie ... I can tweak existing scripts to bend them to my will, but I'm still in the process of learning basic concepts.

So... How would you folks fix this? Smilie Am I on the right track with setting $| to 1, or would moving to sysread/syswrite be a better idea?

Or rewrite it in C? Smilie

Any and all comments welcome. Thanks in advance!

Last edited by rcsteiner; 05-19-2011 at 07:32 PM.. Reason: s/si/is
# 2  
Old 05-20-2011
You could look into sysopen and sysread. They are lower level I/O functions that work unbuffered (unlike <FILEHANDLE> operator).
Code:
sysopen(FILEHANDLE, $name, O_RDONLY) or die $!;

Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Monitor and capture the latest entry from the log file

Hi, I want to monitor a log file using tail -f command and search for a specific string on the most recent entry from the file. If the search string matches with the most recent or last line from the file, I want send an email to the people with the message. tail -f service.log|tail -n 1 ... (5 Replies)
Discussion started by: svajhala
5 Replies

2. Shell Programming and Scripting

Selecting latest entry in the log file

Hi there I am trying to write a script where I will need to look for a specific word in the log file and I am aware this can be done by grep for example. As there will be multiple entries for this I want to grep the last one to enter the log... how would I go about this - would I have to use... (5 Replies)
Discussion started by: simpsa27
5 Replies

3. Shell Programming and Scripting

Parsing log file and print latest number in loop

Hello All, I have an awk script which parses my log file and prints number grepping from a specific line/pattern, now i have to come with a shell script to continue reading the log untill the job is completed, which i would know while reading session log untill process encounters a final... (1 Reply)
Discussion started by: Ariean
1 Replies

4. Shell Programming and Scripting

Grep the Content of a LOG File which has latest Date and Time

Hi All, Need a small help. I have a log file which keeps updating for every Minute with multiple number of lines. I just want to grep few properties which has latest Date and Time to it. How do i do it? I wanted to grep a property by name "Reloading cache with a maximum of" from the... (4 Replies)
Discussion started by: nvindraneel
4 Replies

5. Shell Programming and Scripting

Perl :How to print the o/p of a Perl script on console and redirecting same in log file @ same time.

How can i print the output of a perl script on a unix console and redirect the same in a log file under same directory simultaneously ? Like in Shell script, we use tee, is there anything in Perl or any other option ? (2 Replies)
Discussion started by: butterfly20
2 Replies

6. Shell Programming and Scripting

Delete log file entries based on the Date/Timestamp within log file

If a log file is in the following format 28-Jul-10 ::: Log message 28-Jul-10 ::: Log message 29-Jul-10 ::: Log message 30-Jul-10 ::: Log message 31-Jul-10 ::: Log message 31-Jul-10 ::: Log message 1-Aug-10 ::: Log message 1-Aug-10 ::: Log message 2-Aug-10 ::: Log message 2-Aug-10 :::... (3 Replies)
Discussion started by: vikram3.r
3 Replies

7. Shell Programming and Scripting

how can i pick the latest log file as per below

in the below .. i want to pick the latest logfile which is having JPS.PR inside.. that means i want particularly "spgport040408041223.log:@@@@@@@@ 04:13:09 Adding: JPS.PR." which is latest among these.. is it possible to compare the current time with logfile time ? reptm@xblr0758rop>... (4 Replies)
Discussion started by: mail2sant
4 Replies

8. Shell Programming and Scripting

search latest version of log file

Have checked the forums and couldnt locate help on this. I want to grep a log file for a pattern using a script - I need to grep the latest log file and not sure how I am able to ensure I am greping the latest log file. Here is sample of log files for yestersday and I effectively need to grep... (10 Replies)
Discussion started by: frustrated1
10 Replies

9. UNIX for Dummies Questions & Answers

want to cat the latest log file created

everytime a new logfile get created at certain interval of time and i want a simple shell script program which cat the lastest log file when manually excuted (1 Reply)
Discussion started by: vkandati
1 Replies

10. UNIX for Dummies Questions & Answers

latest status of an field in a log file

Hi I have got a log file which is like: id status --------------------- 12345 status1.true 12345 status2.true 12345 status3.false 12345 status4.true 23452 status5.true 23452 status6.true 23452 status7.false 65243 ... (2 Replies)
Discussion started by: encrypted
2 Replies
Login or Register to Ask a Question