help with pipe

Discussion in 'Perl Misc' started by bjlockie, Oct 16, 2011.

  1. bjlockie

    bjlockie Guest

    Create ./channels.conf with the single line:
    CBC:539000000:8VSB:49:52:3


    This code never gets to 'here3'.
    I think because the command ping never finishes (ping is an example
    command, there are no switches to make the real command stop).
    I've seen similar code working elsewhere.


    my $cmd = 'ping google.ca >/dev/null |';

    open( ZAP, $cmd ) || die "can't fork: $!";

    print $cmd . "\n";

    print "here2\n";

    while (my $line = <ZAP>) {
    print $line;
    }

    print "here3\n";
     
    bjlockie, Oct 16, 2011
    #1
    1. Advertising

  2. bjlockie <> wrote:
    > This code never gets to 'here3'.
    > I think because the command ping never finishes (ping is an example
    > command, there are no switches to make the real command stop).
    > I've seen similar code working elsewhere.


    > my $cmd = 'ping google.ca >/dev/null |';
    > open( ZAP, $cmd ) || die "can't fork: $!";


    You'd nowadays better use the three-argument form of open
    and variables for file handles:

    my $cmd = 'ping google.ca > /dev/null';
    open my $zap, '-|', $cmd or die "can't fork: $!";

    > print $cmd . "\n";
    > print "here2\n";
    > while (my $line = <ZAP>) {
    > print $line;
    > }
    > print "here3\n";


    Yes, of course, if ping never finishes, why should the loop
    terminate? If you want it to end you must decide on a condi-
    tion and implement that. One possibility would be to stop
    after a certain number of lines - add a counter that you
    increment in the loop and use in the loop condition. Another
    condition could be that you only want to read for a certain
    time, this could be dealt with with by setting up a timer (e.g.
    with the alarm() function) that raises the SIGALRMsignal and
    kill the process in the handler for that signal (the PID of
    the spawned process is what open returns). Something like

    use strict;
    use warnings;
    my $cmd = 'ping google.ca > /dev/null';
    my $pid = open my $zap, '-|', $cmd or die "can't fork: $!";
    $SIG{ ALRM } = sub { kill 'TERM', $pid };
    print "here2\n";
    alarm 3;
    while ( my $line = <$zap> ) {
    print $line;
    }
    print "here3\n";

    should do the job of getting out of the loop after 3 seconds.
    Sorry, without knowing what you want to achieve it's a bit
    difficult to be more specific.

    Regards, Jens
    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
     
    Jens Thoms Toerring, Oct 16, 2011
    #2
    1. Advertising

  3. On 2011-10-16 07:57, bjlockie <> wrote:
    > Create ./channels.conf with the single line:
    > CBC:539000000:8VSB:49:52:3
    >
    >
    > This code never gets to 'here3'.


    Jens already explained that.

    > I think because the command ping never finishes (ping is an example
    > command, there are no switches to make the real command stop).
    > I've seen similar code working elsewhere.
    >
    >
    > my $cmd = 'ping google.ca >/dev/null |';
    >
    > open( ZAP, $cmd ) || die "can't fork: $!";


    What do you expect to read from the pipe? You have redirected the
    standard output (which would normally go to the pipe) to /dev/null.

    hp
     
    Peter J. Holzer, Oct 16, 2011
    #3
  4. bjlockie <> wrote:
    >This code never gets to 'here3'.
    >I think because the command ping never finishes (ping is an example
    >command, there are no switches to make the real command stop).
    >I've seen similar code working elsewhere.
    >
    >
    > my $cmd = 'ping google.ca >/dev/null |';
    >
    > open( ZAP, $cmd ) || die "can't fork: $!";


    This has nothing to do with fork. A more accurate message would be
    "can't run $cmd because $!"

    >print $cmd . "\n";
    >
    >print "here2\n";
    >
    > while (my $line = <ZAP>) {
    > print $line;
    > }
    >
    >print "here3\n";


    Well, of course it doesn't. $cmd never terminates, therefore ZAP is
    never closed, and therefore the while loop can't terminate either,
    because there is always the chance, that after 1000 eternities there
    might be output from $cmd.

    I am not sure what your goal is here.
    If you just want to run the other command while ignoring its output,
    then just start it in the background or fork() a new process.
    If you want to capture part of the output then you will have to decide
    what part of that output is relevant to you: the first x lines, the
    first y hours, the first z characters, all output until a certain
    pattern, .... and use that as the termination condition for the loop.

    jue
     
    Jürgen Exner, Oct 16, 2011
    #4
  5. bjlockie

    bjlockie Guest

    On Oct 16, 7:36 am, Jürgen Exner <> wrote:
    > bjlockie <> wrote:
    > >This code never gets to 'here3'.
    > >I think because the command ping never finishes (ping is an example
    > >command, there are no switches to make the real command stop).
    > >I've seen similar code working elsewhere.

    >
    > >    my $cmd = 'ping google.ca >/dev/null |';

    >
    > >    open( ZAP, $cmd ) || die "can't fork: $!";

    >
    > This has nothing to do with fork. A more accurate message would be
    > "can't run $cmd because $!"
    >
    > >print $cmd . "\n";

    >
    > >print "here2\n";

    >
    > >    while (my $line = <ZAP>) {
    > >        print $line;
    > >    }

    >
    > >print "here3\n";

    >
    > Well, of course it doesn't. $cmd never terminates, therefore ZAP is
    > never closed, and therefore the while loop can't terminate either,
    > because there is always the chance, that after 1000 eternities there
    > might be output from $cmd.
    >
    > I am not sure what your goal is here.
    > If you just want to run the other command while ignoring its output,
    > then just start it in the background or fork() a new process.
    > If you want to capture part of the output then you will have to decide
    > what part of that output is relevant to you: the first x lines, the
    > first y hours, the first z characters, all output until a certain
    > pattern, .... and use that as the termination condition for the loop.
    >
    > jue


    my $cmd = 'ping google.ca
    |';

    open( ZAP, $cmd ) || die "can't fork:
    $!";

    print $cmd .
    "\n";

    print
    "here2\n";

    my $numLines =
    0;

    while (($numLines < 10) && (my $line = <ZAP>))
    {
    print
    $line;
    $numLines+
    +;
    }

    print "here3\n";


    That doesn't exit the while loop and it prints the ping output to the
    screen.
     
    bjlockie, Oct 16, 2011
    #5
  6. bjlockie <> wrote:
    >On Oct 16, 7:36 am, Jürgen Exner <> wrote:
    >> bjlockie <> wrote:
    >> >This code never gets to 'here3'.
    >> >I think because the command ping never finishes (ping is an example
    >> >command, there are no switches to make the real command stop).
    >> >I've seen similar code working elsewhere.

    >>
    >> >    my $cmd = 'ping google.ca >/dev/null |';

    >>
    >> >    open( ZAP, $cmd ) || die "can't fork: $!";

    >>
    >> This has nothing to do with fork. A more accurate message would be
    >> "can't run $cmd because $!"
    >>
    >> >print $cmd . "\n";

    >>
    >> >print "here2\n";

    >>
    >> >    while (my $line = <ZAP>) {
    >> >        print $line;
    >> >    }

    >>
    >> >print "here3\n";

    >>
    >> Well, of course it doesn't. $cmd never terminates, therefore ZAP is
    >> never closed, and therefore the while loop can't terminate either,
    >> because there is always the chance, that after 1000 eternities there
    >> might be output from $cmd.
    >>
    >> I am not sure what your goal is here.
    >> If you just want to run the other command while ignoring its output,
    >> then just start it in the background or fork() a new process.
    >> If you want to capture part of the output then you will have to decide
    >> what part of that output is relevant to you: the first x lines, the
    >> first y hours, the first z characters, all output until a certain
    >> pattern, .... and use that as the termination condition for the loop.


    [replacing program with better readable formatting]

    use warnings;
    use strict;
    my $cmd = 'ping google.ca|';

    open( ZAP, $cmd ) || die "can't fork:$!";

    print $cmd ."\n";
    print "here2\n";
    my $numLines = 0;

    while (($numLines < 10) && (my $line = <ZAP>)){
    print $line;
    $numLines++;
    }
    print "here3\n";

    >That doesn't exit the while loop and it prints the ping output to the
    >screen.


    Can't repro your problem. It does stop for me. And if I replace the 10
    with a lower number, e.g. 4, it will stop even in the middle of the ping
    reports.

    jue
     
    Jürgen Exner, Oct 16, 2011
    #6
  7. bjlockie

    bjlockie Guest

    On Oct 16, 12:47 pm, Jürgen Exner <> wrote:
    > bjlockie <> wrote:
    > >On Oct 16, 7:36 am, Jürgen Exner <> wrote:
    > >> bjlockie <> wrote:
    > >> >This code never gets to 'here3'.
    > >> >I think because the command ping never finishes (ping is an example
    > >> >command, there are no switches to make the real command stop).
    > >> >I've seen similar code working elsewhere.

    >
    > >> >    my $cmd = 'ping google.ca >/dev/null |';

    >
    > >> >    open( ZAP, $cmd ) || die "can't fork: $!";

    >
    > >> This has nothing to do with fork. A more accurate message would be
    > >> "can't run $cmd because $!"

    >
    > >> >print $cmd . "\n";

    >
    > >> >print "here2\n";

    >
    > >> >    while (my $line = <ZAP>) {
    > >> >        print $line;
    > >> >    }

    >
    > >> >print "here3\n";

    >
    > >> Well, of course it doesn't. $cmd never terminates, therefore ZAP is
    > >> never closed, and therefore the while loop can't terminate either,
    > >> because there is always the chance, that after 1000 eternities there
    > >> might be output from $cmd.

    >
    > >> I am not sure what your goal is here.
    > >> If you just want to run the other command while ignoring its output,
    > >> then just start it in the background or fork() a new process.
    > >> If you want to capture part of the output then you will have to decide
    > >> what part of that output is relevant to you: the first x lines, the
    > >> first y hours, the first z characters, all output until a certain
    > >> pattern, .... and use that as the termination condition for the loop.

    >
    > [replacing program with better readable formatting]
    >
    > use warnings;
    > use strict;
    > my $cmd = 'ping google.ca|';
    >
    > open( ZAP, $cmd ) || die "can't fork:$!";
    >
    > print $cmd ."\n";
    > print "here2\n";
    > my $numLines = 0;
    >
    > while (($numLines < 10) && (my $line = <ZAP>)){
    >     print $line;
    >     $numLines++;}
    >
    > print "here3\n";
    >
    > >That doesn't exit the while loop and it prints the ping output to the
    > >screen.

    >
    > Can't repro your problem. It does stop for me. And if I replace the 10
    > with a lower number, e.g. 4, it will stop even in the middle of the ping
    > reports.
    >
    > jue


    I was just going to update my post saying it works now. :)
     
    bjlockie, Oct 16, 2011
    #7
  8. bjlockie

    bjlockie Guest

    On Oct 16, 12:47 pm, Jürgen Exner <> wrote:
    > bjlockie <> wrote:
    > >On Oct 16, 7:36 am, Jürgen Exner <> wrote:
    > >> bjlockie <> wrote:
    > >> >This code never gets to 'here3'.
    > >> >I think because the command ping never finishes (ping is an example
    > >> >command, there are no switches to make the real command stop).
    > >> >I've seen similar code working elsewhere.

    >
    > >> >    my $cmd = 'ping google.ca >/dev/null |';

    >
    > >> >    open( ZAP, $cmd ) || die "can't fork: $!";

    >
    > >> This has nothing to do with fork. A more accurate message would be
    > >> "can't run $cmd because $!"

    >
    > >> >print $cmd . "\n";

    >
    > >> >print "here2\n";

    >
    > >> >    while (my $line = <ZAP>) {
    > >> >        print $line;
    > >> >    }

    >
    > >> >print "here3\n";

    >
    > >> Well, of course it doesn't. $cmd never terminates, therefore ZAP is
    > >> never closed, and therefore the while loop can't terminate either,
    > >> because there is always the chance, that after 1000 eternities there
    > >> might be output from $cmd.

    >
    > >> I am not sure what your goal is here.
    > >> If you just want to run the other command while ignoring its output,
    > >> then just start it in the background or fork() a new process.
    > >> If you want to capture part of the output then you will have to decide
    > >> what part of that output is relevant to you: the first x lines, the
    > >> first y hours, the first z characters, all output until a certain
    > >> pattern, .... and use that as the termination condition for the loop.

    >
    > [replacing program with better readable formatting]
    >
    > use warnings;
    > use strict;
    > my $cmd = 'ping google.ca|';
    >
    > open( ZAP, $cmd ) || die "can't fork:$!";
    >
    > print $cmd ."\n";
    > print "here2\n";
    > my $numLines = 0;
    >
    > while (($numLines < 10) && (my $line = <ZAP>)){
    >     print $line;
    >     $numLines++;}
    >
    > print "here3\n";
    >
    > >That doesn't exit the while loop and it prints the ping output to the
    > >screen.

    >
    > Can't repro your problem. It does stop for me. And if I replace the 10
    > with a lower number, e.g. 4, it will stop even in the middle of the ping
    > reports.
    >
    > jue


    Thanks for the help.
     
    bjlockie, Oct 16, 2011
    #8
  9. bjlockie wrote:
    >
    > my $cmd = 'ping google.ca |';
    >
    > open( ZAP, $cmd ) || die "can't fork: $!";
    >
    > print $cmd . "\n";
    >
    > print "here2\n";
    >
    > my $numLines = 0;
    >
    > while (($numLines< 10)&& (my $line =<ZAP>)) {
    > print $line;
    > $numLines++;
    > }
    >
    > print "here3\n";
    >
    >
    > That doesn't exit the while loop and it prints the ping output to the
    > screen.


    Don't do it like that. You are not testing whether the value returned
    from readline is defined. A better way would be:


    my @cmd = qw/ ping google.ca /;

    open my $ZAP, '-|', @cmd or die "Cannot open pipe from '@cmd' because: $!";

    print "@cmd\n";

    print "here2\n";

    while ( my $line = <$ZAP> ) {
    last if $. == 10;
    print $line;
    }

    close $ZAP or warn $! ? "Error closing '@cmd' pipe: $!"
    : "Exit status $? from '@cmd'";

    print "here3\n";

    __END__



    John
    --
    Any intelligent fool can make things bigger and
    more complex... It takes a touch of genius -
    and a lot of courage to move in the opposite
    direction. -- Albert Einstein
     
    John W. Krahn, Oct 16, 2011
    #9
  10. bjlockie

    Guest

    I am wondering if the compression zlib in python could be upgraded to the iterable input and output for different compression algorithm experiments that will outperform the speed of pipelines for all i/o of big chunks.

    This is my suggestion. Maybe this is good for talented young to try to gain insights in python modules by just improving an existed one.
     
    , Oct 17, 2011
    #10
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Tomas Penc
    Replies:
    3
    Views:
    36,110
  2. lee, wonsun
    Replies:
    1
    Views:
    505
    Jack Klein
    Nov 2, 2004
  3. Junhua Deng (AL/EAB)

    socket.error: (32, 'Broken pipe'): need help

    Junhua Deng (AL/EAB), Oct 27, 2005, in forum: Python
    Replies:
    1
    Views:
    1,198
    dcrespo
    Oct 27, 2005
  4. Jeremy Jones
    Replies:
    0
    Views:
    5,778
    Jeremy Jones
    Oct 27, 2005
  5. Replies:
    1
    Views:
    247
    Ben Morrow
    Jun 2, 2004
Loading...

Share This Page