gnu@perl has asked for the wisdom of the Perl Monks concerning the following question:
The problem I am having is this, I need the part that loads the array @hosts to only be executed in the parent not the child, but the fork comes below in the block that depends on @hosts being populated. The problem is that the loading of @hosts is being done in every child. Not only is this not efficient, but I am getting multiple reports of bad ip's written to the log file.
How can I, prior to having $pid set in the fork, make the block that loads @hosts execute only in the parent?
#!/usr/bin/perl -w use strict; use Net::Ping; my $source_file = (shift || "/tmp/ping_list.txt"); my $good_out = "/tmp/good_ips.txt"; my $bad_out = "/tmp/bad_ips.txt"; my %pid_to_host; my %host_result; my @hosts; $|++; open(GOOD,">$good_out") or die "Cannot open output file $good_out: $!\n"; open(BAD,">$bad_out") or die "Cannot open output file $bad_out: $!\n"; open(IPS,"$source_file") or die "Cannot open source file $source_file: $!\n"; for (<IPS>) { chomp; s/ *//; s/\cM//; if ($_ =~ m/^\d+\.\d+\.\d+\.\d+$/) { push(@hosts,$_); } else { print BAD "$_ : NOT A VALID IP ADDRESS\n"; } } for (@hosts) { wait_for_a_kid() if keys %pid_to_host > 50; if ( my $pid = fork ) { # parent $pid_to_host{$pid} = $_; } else { # child exit !ping_a_host($_); } } 1 while wait_for_a_kid(); for (sort keys %host_result) { print GOOD "$_\n" if ($host_result{$_}); print BAD "$_\n" if (!$host_result{$_}); } sub ping_a_host { my $host = shift; my $p = Net::Ping->new('tcp',5); $p->ping($host) ? 1 : 0; } sub wait_for_a_kid { my $pid = wait; return 0 if $pid < 0; my $host = delete $pid_to_host{$pid} or warn("Why did I see $pid ($?)\n"), next; $host_result{$host} = $? ? 0 : 1; 1; }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Forkin around
by tall_man (Parson) on Dec 12, 2002 at 20:19 UTC | |
by gnu@perl (Pilgrim) on Dec 12, 2002 at 21:02 UTC |