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

The code below is from a cgi-script from a prior admin. In this sub the section for tail with grep does not display back. It seems the grep command is not working. I did remove the pipe grep from the line to make sure the if logic was working. it will display the logs, but if I try with the grep line and give it a host it will not display. I need a kick start.

##### sub tail_file { my $node = shift; my $command = (); if ($node =~ /all nodes/i) { $command = "tail -100f $logdir/syslog"; }else{ $command = "tail -100f $logdir/syslog | grep -i $node"; } my $count = 0; print "<h2>Tailing /var/log/syslog...</h2><br>\n"; open (TAIL,"$command |") or die "Can't open TAIL($command):$!\n"; while ($count <= $max) { chomp(my $line = <TAIL>); $line =~ s/\s/$space/g; print "$line<br>\n"; $count++; maxed_out() if $count >= $max } } #####

Replies are listed 'Best First'.
Re: Too many pipes?
by Eliya (Vicar) on Feb 10, 2012 at 18:32 UTC

    Presumably a buffering issue...  (i.e., grep doesn't output anything before its buffer has filled up).

    If your grep supports the option, you might want to try

    ... | grep --line-buffered ...

    (See also Re^2: Reading from a command pipe )

    Another solution would be to implement the grepping in Perl, and do away with the system grep altogether.

      Eliya, You hit it. Unfortunatly my grep does not support the --line-buffered option. I think letting perl do it might be the way to go. I will have to check to see how much I will have to change in this code. Thanks for the suggestions. -Kevin
Re: Too many pipes?
by JavaFan (Canon) on Feb 10, 2012 at 18:25 UTC
    How did you determine it's the grep that "does not work"? Perhaps $node doesn't contain what you think it does? Or contains something special to the shell? Or perhaps what you're looking for isn't in the first $max lines you're examining?

    Do you get a different result if you run the command from the command line?

      I can let the sub run with the "all nodes" in the $node so just the tail will run and it works. If I put anything in $node I get nothing back. Even if the node is something that was returned in all nodes. My only other check was to remove the grep from the elseif line to make sure that the logic was working when $node is other than all nodes. and I get the same output as from the "all nodes" tail. from command line I get what is expected.
Re: Too many pipes?
by kc6ovd (Acolyte) on Feb 15, 2012 at 13:39 UTC

    Ok so I rewrote the sub letting perl handle the work rather than system calls.

    This is a bit sloppy I admit. But it is a working solution to the issues. Keep in mind this is feeding a CGI script on a system I do not have access to. All the output is displayed to the user via a web browser. Please comment on any clean up.

    ##### sub tail_file { my $node = shift; my $name="/var/log/syslog"; my $x = -1; if ($node =~ /all nodes/i){ $x = 15; } print "<h2>Tailing /var/log/syslog...</h2><br>\n"; use File::Tail; my $file=File::Tail->new(name=>$name, tail=>$x); while (defined(my $line=$file->read)) { if ($node =~ /all nodes/i) { print "$line<br>\n"; }else{ my @line2 = grep {/$node/i} $line; foreach my $line3 (@line2) { chomp $line3; $line3 =~ s/\s/$space/g; print "$line3<br>\n"; } } } } #####