我一直在尝试使用Perl编写一个简单的ping扫描器供内部使用。因为它扫描一个24位的CIDR网络,所以如果脚本在一个线程中运行,则运行时间太长。我已经尝试添加fork功能以加快进程,但是我的
first attempt
因为在任何给定时间只有一个子进程处于活动状态,所以占用的时间几乎相同。
我读到了关于
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";
当我扫描内部网络时,输出为:
$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
如结果所示,执行成功扫描的线程将打印“向上”消息,干净地退出,并由父进程获取。同时,其他251个线程仍挂在“/sbin/init”上,这可以通过快速的“ps-ef”列表看到。如果我在exit语句之前的子处理块中添加了一个'print'子进程:$currip ending \n“”,我将在“我的perl脚本退出”之后从终端上的其余251个进程中获取输出。
这是怎么回事?我认为$sig chld子例程加上waitpid循环将获取所有子进程,并确保系统中没有僵尸/悬空进程。
同样,我也希望能够在任何给定的时间运行特定数量的子进程,例如,“n”子进程同时运行,每当一个退出父进程时,如果需要,会启动另一个子进程,但在任何给定的时刻都不超过“n”子进程。这有可能吗?如果是,我可以得到一些伪代码来帮助指导我吗?