Re: Executing independet commands in PERL
by dvergin (Monsignor) on Mar 04, 2001 at 19:26 UTC
|
Perhaps
ping -t perlmonks.org > ping.log
isn't working because the -t option goes
forever until you stop it. So the the file ping.log
is never closed. (You might take a look at the
-n option.)
You don't make clear if you *need* a log file or if that
is just your strategy for accomplishing your analysis.
If you are open to other ways of grabbing the data, you
might skip redirecting the results to a file.
Consider using back-ticks or qx(...) and then just
wait for each run before proceeding. Here's a brief
example with a generous sprinkling of intermediate
variables for clarity.
#!/usr/bin/perl5 -w
use strict;
my ($avg_time, $raw_data, @times,
$time_count, $total_time);
my $repeats = 5;
my $addr = 'www.perlmonks.net';
for (my $i = 1; $i <= $repeats; $i++) {
$raw_data = `ping $addr`; # NOTE back-ticks
# Now do something interesting. We'll just...
@times = $raw_data =~ /time=(\d+)/g;
$total_time = 0;
$time_count = 0;
for (@times) {
$total_time += $_;
$time_count++;
}
$avg_time = $total_time / $time_count;
print "$i. Average time: ${avg_time}ms\n";
}
Which produces:
1. Average time: 61.25ms
2. Average time: 61.75ms
3. Average time: 60.75ms
4. Average time: 62ms
5. Average time: 62.25ms
You could, of course, just collect your data in the larger
for loop and then do your analysis on the
whole thing after you have collected as many ping
responses as you need. Just make sure you don't set the
data gathering processes to run
forever. ;-) | [reply] [d/l] [select] |
|
|
It solves the ping problem, but doesn't solve "executing another program WITHOUT stoping mine".
This ping thing came into my mind, because where I'm living now I have a BAD ISDN connection that needs to be controlled, so I started opening a window and ping perlmonks -t and just look at it.
After, as a good programmer, I saw so many data passing in the screen and the only thing that I could think about was "ANALYSE!!!!!", so I changed the ping -t into a log file, and started to make a little program that got a little bit bigger, and bigger, and finally, I wanted to put all toghether, and then... the rest you know...
So my main question is not how to ping and log, or how to ping and analyse, is how to execute something else without worying about it after started...
I got a lot of answers that worked below like as for example system "open ping -t perlmonks.org >ping.log".
That one worked perfeclty for what I needed, like that I can open a text editor, I can open a Browser, and in windows, I can say the file that I want to open, or the site (in the case of the browser)...
-------
[]'s
FiReWaLL
The only thing you regret in life, is the risk you don't take.
| [reply] [d/l] |
Re: Executing independet commands in PERL
by AgentM (Curate) on Mar 05, 2001 at 00:41 UTC
|
It seems that you have more than enough help posted above, so let me just quickly make sure that you understand the differences between fork, exec, and system. They are very often confusing. Your analysis of exec is not entirely correct.
- exec replaces the current process binary with a new executable binary. Hence, if you ran a perl script and called exec in the same process, you would lose anything that you wrote in that perl script (with some exceptions which are not relevant under Winduz).
- fork will create a new process and populate it with instructions or a new process, hence giving birth to
- system which is essentially a fork and exec. The process creates a child process and populates it with the shell command. It then proceeds to waitpid on that system call.
AgentM Systems nor Nasca Enterprises nor
Bone::Easy nor Macperl is responsible for the
comments made by
AgentM. Remember, you can build any logical system with NOR.
| [reply] |
Re: Executing independet commands in PERL
by ColtsFoot (Chaplain) on Mar 04, 2001 at 16:04 UTC
|
You are going to need to fork a process that performs the ping and then in the parent you should be able to examine the log file.
If you are using ActiveState perl 5.6 then
Take a look at this
Hope this helps | [reply] |
|
|
Of course, it's still to note that the fork() implementation of ActiveState Perl, while amazing, does not yet work correctly, as the Win32 API dosen't support fork() in a native way. It's easy to break forking programs by passing sockets to your children.
If you don't need to pass information between your parent and child process, it might be easier to use system() calls to start new instances of the child script(s)...
| [reply] |
Re: Executing independet commands in PERL
by btrott (Parson) on Mar 05, 2001 at 00:13 UTC
|
For information on starting up another process and letting it
run independently of your own, check out perlipc.
But you may want to try and get rid of the external program
altogether and use Net::Ping. Then you have control
over the entire process.
An example from the docs:
$p = Net::Ping->new();
print "$host is alive.\n" if $p->ping($host);
$p->close();
| [reply] [d/l] |
|
|
Net::Ping doesn't use ICMP, but UDP/TCP to connect to the echo port of a machine. I tried using it, but found out you couldn't use ICMP and most machines don't have their echo port enabled for obvious reasons... In my current version I use Open3. The options for ping probably don't apply to Windows ping. I use FreeBSD 4.2 here.
#!/usr/local/bin/perl5 -w
use IPC::Open3;
use Symbol;
# .ping contains hostnames, each on a seperate line.
open(HOSTS, "<.ping") || die("Can't open hostsfile! ($!)\n");
@hosts = <HOSTS>;
close(HOSTS);
%PING = ();
%STATUS = (
-1 => "Host not found",
0 => "Not done",
1 => "Host is alive",
2 => "No reply from host",
);
foreach $host (@hosts) {
chomp $host;
$WTR = gensym();
$RDR = gensym();
$ERR = gensym();
$PING{$host}{'PID'} = open3($WTR, $RDR, $ERR, "/sbin/ping -n -q -c 1
+ $host");
close($WTR);
while (<$RDR>) { $PING{$host}{'OUT'} .= $_; }
while (<$ERR>) { $PING{$host}{'ERR'} .= $_; }
$PING{$host}{'STATUS'} = 0;
}
foreach $host (keys %PING) {
if(defined($PING{$host}{'ERR'})) {
if($PING{$host}{'ERR'} =~ /Unknown host/) {
$PING{$host}{'STATUS'} = -1;
next;
}
}
if($PING{$host}{'OUT'} =~ /.*, (.*) packets received.*/) {
$PING{$host}{'STATUS'} = ($1 == 1?1:2);
}
}
foreach $host (keys %PING) {
printf "%-30s %s\n", $host, $STATUS{$PING{$host}{'STATUS'}};
}
| [reply] [d/l] |
|
|
$p = Net::Ping->new("icmp");
foreach $host (@host_array)
{
print "$host is ";
print "NOT " unless $p->ping($host, 2);
print "reachable.\n";
sleep(1);
}
$p->close();
| [reply] [d/l] |
|
|
Re: Executing independet commands in PERL
by the_slycer (Chaplain) on Mar 04, 2001 at 22:19 UTC
|
With Windows, if you don't read results from the program you
want to execute into a variable or something, then the easiest
way is to use the "start" command. So, something like system ("start path\to\command");
Normally works quite well. The nice thing about this is that
your code only waits for "start" to finish (which occurs almost
instantly) | [reply] [d/l] |
Re: Executing independet commands in PERL
by Anonymous Monk on Mar 04, 2001 at 23:28 UTC
|
Try something like @log=qx/ping -t perlmonks.org/.
Haven't tried it, but I think the qx operator is what
you need, it returns the output of an external command.
See man perlop, too.
| [reply] |
|
|
| [reply] [d/l] |
|
|
| [reply] |
Re: Executing independent commands in PERL
by swr (Initiate) on Mar 05, 2001 at 16:04 UTC
|
Is there some reason nobody has suggested open(PING, "ping -t perlmonks.org|") ? Or does that not work in the windows perl? If recording the logfile is important, you could always write the output to the logfile from perl as the data is read in. | [reply] |