退出叉子但回到父母 [英] Exit a fork but return to parent

查看:83
本文介绍了退出叉子但回到父母的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我第一次尝试使用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.

这篇关于退出叉子但回到父母的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆