aks*_*aks 4 perl fork ipc zombie-process
我一直在尝试使用Perl编写一个简单的ping扫描器供内部使用.由于它扫描24位CIDR网络,因此如果脚本在单个线程中运行,则运行时间太长.我已经尝试添加fork功能来加速进程,但我的第一次尝试几乎同时进行,因为在任何给定时间只有一个子进程处于活动状态.
我在perlipc文档和Perl Cookbook中阅读了子进程,并提出了第二个版本:
##Install the CHLD SIG handler
$SIG{CHLD} = \&REAPER;
sub REAPER {
my $childPID;
while (( $childPID = waitpid(-1, WNOHANG)) > 0) {
print "$childPID exited\n";
}
$SIG{CHLD} = \&REAPER;
}
my $kidpid;
for (1 .. 254) {
my $currIP = join ".", (@ipSubset[0,1,2], $_);
die "Could not fork()\n" unless defined ($kidpid = fork);
if ($kidpid) {
#Parent process
#Does nothing
}
else {
#Child process
my $pingConn = Net::Ping->new(); #TCP
say "$currIP up" if $pingConn->ping($currIP);
$pingConn->close();
#Nothing else to do
exit;
}
}
say "Finished scanning $ipRange/24";
Run Code Online (Sandbox Code Playgroud)
当我扫描内部网络时,输出是:
$perl pingrng2.pl 192.168.1.1
192.168.1.2 up
5380 exited
192.168.1.102 up
192.168.1.100 up
5478 exited
5480 exited
Finished scanning 192.168.1.1/24
Run Code Online (Sandbox Code Playgroud)
从结果中可以看出,执行成功扫描的线程打印"up"消息,干净地退出并由父进程获取.其他251个线程同时悬挂在'/ sbin/init'上,如快速'ps -ef'列表所示.如果我添加一个'print'Child:$ currIP在退出语句之前的子处理块中结束\n"'我在我的perl脚本退出之后从我的终端上的其余251个进程获得输出.
这里发生了什么?我认为$ SIG {CHLD}子程序与waitpid循环相结合将收获所有子进程并确保系统中没有留下僵尸/悬空进程.
同时我也希望能够在任何给定时间运行特定数量的子进程,例如,'n'子进程并发运行,每当退出父进程时,如果需要,则启动另一个子进程但不再有比任何特定时刻的'n'孩子.这可能吗?如果是,我可以获得一些伪代码来帮助指导我吗?
看起来你的父进程在孩子面前完成(因此永远不会有机会收获他们).试试这个:
#!/usr/bin/perl
use 5.010;
use strict;
use warnings;
use Net::Ping;
my @ipSubset = (192, 168, 10);
my $i = 0;
my @pids;
for my $octet (1 .. 254) {
my $currIP = join ".", @ipSubset[0 .. 2], $octet;
die "Could not fork()\n" unless defined (my $pid = fork);
#parent saves chlidren's pids and loops again
if ($pid) {
push @pids, $pid;
next;
}
#child process
my $pingConn = Net::Ping->new;
say "$currIP up" if $pingConn->ping($currIP);
$pingConn->close();
exit;
}
#wait on the children
for my $pid (@pids) {
waitpid $pid, 0;
}
Run Code Online (Sandbox Code Playgroud)