我第一次尝试使用fork
时出现问题。
脚本似乎运行正常,直到我需要它退出fork并返回主脚本。
相反,它完全退出脚本。
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;
}
此时它应该在父脚本中继续并打开一个子程序来解析扫描输出。相反,它完全退出脚本。
我做错了什么?
- = - = - = - =更新 - = - = - = - = 我尝试了下面的Parallel :: ForkManager示例。当作为独立进程运行时,它可以完美地运行。我在子程序中运行代码但是当我尝试时,Perl解释器崩溃了。建议?
#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";
}
答案 0 :(得分:5)
首先,您的脚本不会“完全退出”。它确实等待孩子们完成。或者至少其中一些。你的计算有点偏。
你正在跳过最后的元素。
$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);
您正在执行两次边界元素。
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
,这样可以减少每批次的分叉数量,从而提高批量使用效率。