Equidor has asked for the wisdom of the Perl Monks concerning the following question:
Hello, Monks.
My first query here. I'm excited.
We have a number of machines (Slackware Linux, Perl 5.10) acting as data collectors: each has some number of serial inputs, each serial port writes to a file as stuff (ASCII text) arrives. There is a requirement for real-time viewing of incoming data -- the serial port data files. We came up with an application using Perl/Tk, but in the interest of minimizing our time rebuilding OS's we would rather stay away from X windows and instead have a simple curses application which would ordinarily be the only thing the data viewer user would see. The problem: using Curses::UI::TextViewer, no data ever displays.
To read the data file we discovered a number of sources which all recommended this method:
$errcode = open(FH, " tail -f $filename | ");
What none of these sources mentioned is that each time one of these filehandles is closed, an orphaned tail PID is left hanging out there. We came up with a little package for opening and closing the files which also tracks the tail PID's and disposes of them appropriately. The Perl/Tk code looks like this:
#!/usr/bin/perl use strict; use warnings; use Tk; require "./SFDTail.pm"; . . # SFDTail.pm is our file handling package my $tailer = SFDTail::new(); my $mw = MainWindow->new(); my $txtarea = $mw->Scrolled('Text', ... option stuff ...); . . MainLoop; . . # grabtext() is our Tk::fileevent callback function # $tailer->fh() returns a file handle ($fh), created as: # open($fh, "tail -f -n 20 $self->{file} |"); sub grabtext { # $stuff = <$tailer->fh()> don't work --?? my $glob = $tailer->fh(); my $stuff = <$glob>; $txtarea->insert('end', $stuff); $txtarea->yview('end'); } . . # Tk::Button event callback: select appropriate file, let $tailer ope +n it. # $tailer->tail($file) is where the file gets opened, as above. sub standard { my $unit = shift; # typically 'Unit01', 'Unit02', etc # clean up: close any previous filehandle and kill any tail PID's $tailer->closepipe(); my $file = "/usr/local/scripts/tk/${unit}.txt"; $txtarea->delete('1.0', 'end'); # if data input not active, the file may not be there if ( -f $file ) { if ( $tailer->tail($file) ) { $mw->fileevent($tailer->fh(), 'readable' => \&grabtext); } } else { $txtarea->insert('end', "\n No data for $unit. \n"); } }
The Perl/Tk thing works great, but trying to duplicate that in Curses:UI is not going so well. We're guessing that it's a blocking thing which somewhere between Tk::fileevent and Tk::Mainloop just gets quietly handled for us. We so far have been unable to get Curses::UI to go about its business and also display the results of the piped-tail filehandle. We would be most grateful for any suggestions, and thanks in advance.
< five days later >
Tried the select loop, but I guess I'm too dense to figure out how to get it to behave the way I needed it to. Finally found a workable solution using Curses::UI::POE and POE::Wheel::FollowTail. Thanks everybody for your consideration.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Blocking filehandle (?)
by ikegami (Patriarch) on Aug 24, 2010 at 15:32 UTC | |
by Equidor (Sexton) on Aug 24, 2010 at 23:15 UTC | |
|
Re: Blocking filehandle (?)
by JavaFan (Canon) on Aug 24, 2010 at 14:49 UTC |