Read first few lines from command output

S

sp0_0ky

Hello,

I have a program which generates many lines of output. I only
need the first few (say 10) lines from the top of the output.
I do not require the program to complete all the output (just
need the first few lines).

The following seems to work, however it complains about "Broken
Pipe" since I am closing the pipe once I get the required data.
I was wondering if there is a cleaner way to do this. The key
is that I do not want to wait for the data command to complete.

open(LOTSOFLINES,"mycommand 2>&1|");
count=0;
while (<LOTSOFLINES>)
{
print;
count++;
if ($count > 10)
{
close(LOTSOFLINES);
}
}

Thanks,
JB
 
P

Paul Lalli

I have a program which generates many lines of output. I only
need the first few (say 10) lines from the top of the output.
I do not require the program to complete all the output (just
need the first few lines).

The following seems to work, however it complains about "Broken
Pipe" since I am closing the pipe once I get the required data.
I was wondering if there is a cleaner way to do this. The key
is that I do not want to wait for the data command to complete.

open(LOTSOFLINES,"mycommand 2>&1|");
count=0;

What language is this? Please post real code.
while (<LOTSOFLINES>)
{
print;
count++;
if ($count > 10)
{
close(LOTSOFLINES);
}
}

Just to be pedantic, that would read the first 11 lines, not 10
(assuming it was actually valid Perl code).

Now, as to your question... From perldoc perlipc:
Prematurely closing the read end of a pipe (i.e.
before the process writing to it at the other end
has closed it) will result in a SIGPIPE being
delivered to the writer. If the other end can't
handle that, be sure to read all the data before
closing the pipe.

In other words, it's not a problem your code can do anything about. If
you have access to the other program, configure it to handle SIGPIPE.
If not, you'll have to either live with the "Broken Pipe" error, or
read all the data.

Paul Lalli
 
P

Paul Lalli

Paul said:
Now, as to your question... From perldoc perlipc:
Prematurely closing the read end of a pipe (i.e.
before the process writing to it at the other end
has closed it) will result in a SIGPIPE being
delivered to the writer. If the other end can't
handle that, be sure to read all the data before
closing the pipe.

Whoops. That was from
perldoc -f close
not from perlipc. My mistake.

Paul Lalli
 
S

Sven-Thorsten Fahrbach

On 27 Jul 2005 13:47:26 -0700
Hello,

I have a program which generates many lines of output. I only
need the first few (say 10) lines from the top of the output.
I do not require the program to complete all the output (just
need the first few lines).

The following seems to work, however it complains about "Broken
Pipe" since I am closing the pipe once I get the required data.
I was wondering if there is a cleaner way to do this. The key
is that I do not want to wait for the data command to complete.

open(LOTSOFLINES,"mycommand 2>&1|");
count=0;
while (<LOTSOFLINES>)
{
print;
count++;
if ($count > 10)
{
close(LOTSOFLINES);
}
}

Thanks,
JB

Inserting a 'last' does the trick.

while (<LOTSOFLINES>) {
print;
$count++;
if ($count > 9) {
close (LOTSOFLINES);
last;
}
}

Now perl won't try to get the next line since it never sees the diamond operator in the head of your while loop after the 'last'.
 
M

Mark Overmeer

Inserting a 'last' does the trick.

while (<LOTSOFLINES>) {
print;
$count++;
if ($count > 9) {
close (LOTSOFLINES);
last;
}
}

Now perl won't try to get the next line since it never sees the diamond operator in the head of your while loop after the 'last'.

The file isn't closed if it is too short...

while( <LL> )
{ print;
last if ++$count > 9;
}
close LL;

Or

while( <LL> )
{ print;
last if $.==9;
}

Or

print while <LL> && $. < 10;

Or ...

But it will probably not solve your "broken pipe". A typical warning in
old UNIX programs. You could do
1 while <LL>;
close <LL>;
 
J

John W. Krahn

Mark said:
The file isn't closed if it is too short...

while( <LL> )
{ print;
last if ++$count > 9;
}
close LL;

Or

while( <LL> )
{ print;
last if $.==9;
}

Or

print while <LL> && $. < 10;

That won't print anything because <LL> only assigns to $_ when it is the
only expression in the while condition.

print while defined( $_ = <LL> ) && $. < 10;



John
 
B

Big and Blue

I was wondering if there is a cleaner way to do this. The key
is that I do not want to wait for the data command to complete.

As has been pointed out, it's the process generating the data which is
sent the SIGPIPE and hence would need to handle it.

Since you don't want to wait in your script then, if you can't get the
other side to handle SIGPIPE:

1) read as much as you need to
2) fork()
3) let the child continue to read (and discard) the rest of the input while
4) the parent continues to do what you want it to.

You may wish to get the child to fork twice (so the parent quickly sees
its child die() and so won't wait for it), to close the read handle in the
parent and to detach the child even more (eg: setsid from POSIX), but that
is left up to you....
 
P

Paul Lalli

Sven-Thorsten Fahrbach said:
On 27 Jul 2005 13:47:26 -0700

Inserting a 'last' does the trick.

while (<LOTSOFLINES>) {
print;
$count++;
if ($count > 9) {
close (LOTSOFLINES);
last;
}
}

Now perl won't try to get the next line since it never sees the diamond
operator in the head of your while loop after the 'last'.

It is not the <> operation that causes the broken pipe error, it is the
close() statement. However, assuming the close *does* work, your last
statement will prevent the "read on closed filehandle" warning for the
remainder of the loop.

Paul Lalli
 
S

Sven-Thorsten Fahrbach

It is not the <> operation that causes the broken pipe error, it is the
close() statement. However, assuming the close *does* work, your last
statement will prevent the "read on closed filehandle" warning for the
remainder of the loop.

Paul Lalli

Yes, that's right, I've mistaken that for the actual problem.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top