问题描述
我第一次尝试使用fork
时遇到问题.
I am having an issue with my first attempt at using fork
.
在我需要它退出fork并返回主脚本之前,该脚本似乎运行良好.
The script seems to run fine until I need it to exit the fork and return to the main script.
相反,它会完全退出脚本.
Instead it exits the script entirely.
my @files = glob( "./input/<Input subnets>.txt" ) or die "Can't open HostInventory$!"; # Open the Host Inventory csv files for parsing
foreach my $file ( @files ) {
open (CONFIG, '<', $file) or die "Can't <Input subnets>.txt$!";
my @lines = <CONFIG>;
chomp (@lines);
$m = scalar @lines / 10;
for ( $m ) {
s/\..*//g
};
for ( my $i = 0; $i < @lines; $i += $m ) {
# take a slice of elements from @files
my @lines4 = @lines[$i .. $i + $m];
if ( fork() == 0 ) {
for my $n ( @lines4 ) {
system("Nmap -dns-servers <IP of DNS server> -sn -v $n -oX ./input/ip360_DNS/ip360_DNS$n.xml --send-eth --reason");
}
exit;
}
}
wait for 0 .. @lines/$m;
}
这时,它应该在父脚本中继续并打开一个子例程,该子例程分析扫描的输出.相反,它会完全退出脚本.
At this point it should continue in the parent script and open a subroutine that parses the output of the scan. Instead it exits the script completely.
我在做什么错了?
-=-=-=-=更新-=-=-=-=我尝试了下面的Parallel :: ForkManager示例.当作为独立进程运行时,它可以完美运行.虽然我在子例程中运行代码,但是当我尝试这样做时,Perl解释器崩溃.有建议吗?
-=-=-=-=Update-=-=-=-=I tried the Parallel::ForkManager example below. When run as a standalone process it work perfectly. I am running the code inside of a subroutine though and when I try that, the Perl interpreter crashes. Suggestions?
#1/usr/bin/perl -w
use Parallel::ForkManager;
use strict; # Best Practice
use warnings; # Best Practice
use Getopt::Long; # Add the ability to use command line options
if (!@ARGV) {
&help;
exit 1
}
GetOptions(
full => \&full,
temp => \&temp,
);
#######################################################################
#######################################################################
# #
# Call each function #
# #
#######################################################################
#######################################################################
sub temp {
&speak;
&simple;
&speak2;
exit;
}
sub full {
&speak;
&simple;
&speak2;
exit;
}
sub speak {
print "This is where I wait for 2 seconds\n";
sleep (2);
}
my $process = $$;
print "$process\n";
sub simple {
my $pm = new Parallel::ForkManager(10);
$pm->run_on_finish(
sub { $process;
print "** PID $process\n";
}
);
my @files = glob( "./ping.txt" ) or die "Can't open CMS HostInventory$!"; # Open the CMS Host Inventory csv files for parsing
foreach my $file (@files){
open (CONFIG, '<', $file) or die "Can't ip360_DNS File$!";
my @lines = <CONFIG>;
chomp (@lines);
foreach my $n (@lines) {
# Forks and returns the pid for the child:
my $pid = $pm->start and next;
# ... do some work with $data in the child process ...
system("ping $n >> ./input/$n.txt");
}
$pm->finish; # Terminates the child process
}
}
sub speak2 {
print "In new subroutine\n";
}
推荐答案
首先,您的脚本不会完全退出".它确实等待孩子们完成.或至少其中一些.您的计算有些差.
First of all, your script doesn't "exit completely". It does wait for the children to finish. Or at least some of them. Your calculations are a little off.
您正在跳过最后一个元素.
You're skipping the last elements.
$m = scalar @lines / 10;
for ($m) {s/\..*//g};
等效于
use POSIX qw( floor );
my $m = floor(@lines / 10);
但应该是
use POSIX qw( ceil );
my $m = ceil(@lines / 10);
您要执行两次边界元素.
You're performing the boundary elements twice.
my @lines4 = @lines[$i .. $i + $m];
应该是
my @lines4 = @lines[$i .. $i + $m - 1];
wait for 0 .. @lines/$m;
应该是
use POSIX qw( ceil );
wait for 1 .. ceil(@lines/$m);
或者只是
1 while wait > 0;
更易于使用 Parallel :: ForkManager .
use Parallel::ForkManager qw( );
my $pm = Parallel::ForkManager->new(10); # Max number of children at a time.
$pm->run_on_finish(sub {
my ($pid, $exit, $id, $signaled, $dumped, $data) = @_;
my ($config_qfn, $target) = @$id;
...
});
for my $config_qfn (glob(...)) {
open(my $config_fh, '<', $config_qfn)
or die("Can't open \"$config_qfn\": $!\n");
chomp( my @targets = <$config_fh> );
for my $target (@targets) {
my $pid = $pm->start([$config_qfn, $target])
and next;
exec(...)
or die("exec: $!");
}
}
$pm->wait_all_children();
顺便说一句,您可能已经注意到我停止了分批处理.这使我可以使用exec
而不是system
,这使每个批次的派生数减少了一个,从而使不使用批次的效率更高.
By the way, you may have noticed I stopped doing things in batches. This allowed me to use exec
instead of system
, which reduces the number of forks by one for each batch, making it more efficient to not use batches.
这篇关于退出叉子但回到父母的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!