[CMI.PM] Trapping STDOUT in-process?

Ed Thomson ethomson at ravecomm.com
Thu Oct 7 21:19:03 CDT 2004


Hey Mitch-

qx// will read the entire output into a buffer, and will wait for the 
process to complete before it continues.  So, the program has exited by 
the time you get to your for() loop.

Instead of running the command, then running the for loop over the 
output, try opening the program's output directly and running what's in 
the for() loop inside a while loop reading the input.

Eg:
open(TRACEROUTE, "traceroute $target 2>&1 |") || die;
while(<TRACEROUTE>)
{
   .. print the lines ..
}
close(TRACEROUTE);

I think this will help -- good luck!

-Ed

Mitch Kutzko wrote:
> Hi, folks -- Is there a way for me to read STDOUT on the fly, as it
> happens, before the command I'm execing is complete?
> 
> Background:
> 
> I need to write a script that returns the names of all the hosts involved
> in a traceroute.  This is fairly simple:
> 
> ------------------------------------------------------------
> #!/usr/bin/perl -w
> 
> use strict;
> 
> my $target = "qbridge.bu.edu";  # Default target
> if (defined $ARGV[0]) {         # If they gave a different target
>         $target = $ARGV[0];
> }
> 
> $target = lc($target);          # Lowercase it
> 
> # Get the output text for parsing, and supress console output
> my @results = qx/traceroute $target/;
> my @errors = qx/traceroute $target 2>&1/;
> 
> if (!@results && @errors) {             # What went wrong?
>         print "Uh-oh:\n at errors\n";
>         exit;
> }
> 
> 
> my $lth = scalar @results;      # Get number of lines (= # of hops)
> my $hostname = `hostname -f`;   # Get local  hostname (-f may not work some
> OSs)
> chomp $hostname;                # Remove trailing space
> 
> print "Results: $lth hops from $hostname to $target\n";
> 
> # Iterate over lines/hops to get hostnames
> my $ii=0;
> for ($ii=0;$ii<$lth;$ii++) {
>         my @spot = split ' ', $results[$ii];    # Break on word boundaries
>         $spot[1] = lc($spot[1]);                # Lowercase the name
>         print "$ii) $spot[1]\n";                # Print it
> }
> 
> exit;
> ------------------------------------------------------------
> 
> 
> If the host is pingable, or if the host doesn't actually exist, this works
> fine.
> 
> The problem is the case in which this is likely to be used most often, in
> which a legitimate host doesn't have a route to it at the moment (which is
> why the diagnostic is being run in the first place), and so generates
> output like this:
> 
> [mitch at jhereg advisor]$ traceroute dyn09.iacc-t21.ndsu.nodak.edu
> traceroute to dyn09.iacc-t21.ndsu.nodak.edu (134.129.71.204), 30 hops max,
> 38 byte packets
>  1  netdev98-254 (141.142.98.254)  12.878 ms  0.381 ms  0.341 ms
>  2  sbr0-vlan116.gw.ncsa.edu (141.142.0.65)  0.459 ms  0.543 ms  0.409 ms
>  3  198.17.196.2 (198.17.196.2)  3.025 ms  2.980 ms  3.038 ms
>  4  chin-mren-ge.abilene.ucaid.edu (198.32.11.97)  3.042 ms  3.178 ms
> 3.010 ms
>  5  iplsng-chinng.abilene.ucaid.edu (198.32.8.77)  175.039 ms  237.742 ms
> 256.378 ms
>  6  mn-abilene.northernlights.gigapop.net (192.42.152.170)  27.838 ms
> 27.764 ms  27.763 ms
>  7  ndsu-i2r.northernlights.gigapop.net (192.42.152.173)  34.522 ms  34.154
> ms  34.337 ms
>  8  vlan-107.cc.ndsu.NoDak.edu (134.129.107.100)  44.434 ms  34.303 ms
> 34.304 ms
>  9  * * *
> 10  * * *
> 
> 
> The problem with my script above is that it relies on the command actually
> either completing or failing.  This case is "in-process", and so does neither.
> 
> When run via my script, no output occurs at all, as the qx// never comes back.
> 
> So my question is:
> 
> Is there a way for me to read STDOUT on the fly, as it happens, before the
> command I'm execing is complete?
> 
> Thanks!
> 
> Mitch
> --
> Mitch Kutzko | mitch at dast.nlanr.net | mitch at ncsa.uiuc.edu | 217-333-1199
> http://hobbes.ncsa.uiuc.edu/
> _______________________________________________
> Champaign-Urbana mailing list
> Champaign-Urbana at mail.pm.org
> http://mail.pm.org/mailman/listinfo/champaign-urbana


More information about the Champaign-Urbana mailing list