【问题标题】:Perl: Why does this create thousdands of child processes?Perl:为什么这会创建数千个子进程?
【发布时间】:2010-08-18 01:04:48
【问题描述】:

所以,当我运行这段代码时,它似乎对系统进行了分叉炸弹,你们能帮帮我吗?我要做的就是为每个 appWatch 域和环境启动一个线程。

#!/usr/bin/perl
#
#
#       Starts the mass processes to watch each directory & enviroment.
#
#
#
###################################################################################
use strict;
use warnings;
use POSIX 'setsid';
setsid();
my @domains = (qw(austin batman luke heman drevil joker skeltor drevil goodguy badguy));
my @envs = (qw(qa dev));
        foreach my $env (@envs){
                foreach my $guy (@domains){
                        unless(my $pid = fork()){
                                system("echo $env.$guy");
                                system("sleep 10 ");
                                #system("./appWatch -d $guy -e $env");
                                open PID, ">>pid.lock";
                                print PID $$ . "\n";
                                print "$$ is Parent, $pid is child";
                }
        }
}
                wait();

【问题讨论】:

    标签: perl process fork


    【解决方案1】:

    您的代码应该只创建三个孩子。如果您看到创建了一堆孩子,那么您正在运行不同的代码(或者罪魁祸首是 appWatch 而不是您的代码)。在一个稍微不相关的说明中,您可能应该做一些不同的事情:

    1. fork 有三个可能的返回值,而不是两个
    2. 你必须收割你的孩子或设置系统为你收割他们
    3. 如果你不想返回代码,你应该使用exec而不是system
    4. 如果您不希望 shell 处理参数,则应使用 systemexec 的多参数版本,而不是单参数版本。

    这是我的代码版本:

    $SIG{CHLD}  = "IGNORE"; #auto-reap the children
    my @domains = qw(domains);
    my @envs    = qw(enviromentA enviromentB);
    for my $env (@envs){
            for my $guy (@domains){
                    die "could not fork: $!" unless defined(my $pid = fork);
                    next if $pid;
                    exec "./appWatch", "-d", $guy, "-e", $env;
                    die "exec must have failed";
            }
    }
    

    您更新的代码版本显示了发生的情况。您的孩子不会退出。以下是我将如何编写您的代码:

    #!/usr/bin/perl
    # Starts the mass processes to watch each directory & enviroment.
    
    use strict;
    use warnings;
    use POSIX 'setsid';
    setsid();
    
    my @domains = qw(
        austin  batman luke    heman
        drevil  joker  skeltor drevil
        goodguy badguy
    );
    my @envs = qw(qa dev);
    
    my @pids;
    for my $env (@envs){
        for my $guy (@domains){
            die "could not fork: $!" unless defined(my $pid = fork);
            if ($pid) {
                push @pids, $pid;
                next;
            }
            print "$env.$guy\n";
            sleep 10; #FIXME: I don't know if you really need this
            #exec will replace the child process with appWatch
            exec "./appWatch", "-d", $guy, "-e", $env;
            die "exec failed for some reason";
        }
    }
    for my $pid (@pids) {
        waitpid $pid, 0;
    }
    

    【讨论】:

    • 好的,很酷,一旦我得到系统备份,我会发布错误的代码,但你的代码很好用。谢谢!我的第二个问题,如果可以的话,我该怎么做才能让如果这个脚本被杀死它会杀死它所有的孩子?
    • @Nerdatastic 在我的脑海中,你可以记住数组中的所有子 IP 并使用 END 块来 kill 他们:END { kill 15, @pids }
    • 我刚刚更新了导致系统崩溃的代码,我现在正在使用您修改后的解决方案。
    • @Nerdatastic 我刚刚注意到你在 NovA。你考虑过参加 DC Perl Mongers 会议吗?它是每个月的第一个星期二,就在 Farragut West 地铁站上方 (dc.pm.org)。
    • @Chas,我不知道,但看起来很有趣,我会仔细研究一下!
    【解决方案2】:

    $ cat appWatch
    #! /usr/bin/perl -l
    print "[", join("][" => @ARGV), "]";

    正在运行

    $ unname -a
    Linux mybox 2.6.32-24-generic #39-Ubuntu SMP Wed Jul 28 05:14:15 UTC 2010 x86_64 GNU/Linux

    我没有得到fork 炸弹,只是一个乏味的笛卡尔积:

    $ ./prog.pl
    [-d][域][-e][环境A]
    [-d][域][-e][环境B]

    【讨论】:

    • 如果我启动了我刚刚分叉的系统,我会告诉你最新的代码。它本质上就是这样。 IT 通常不会,但由于某种原因,它会启动数千个进程
    猜你喜欢
    • 2015-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多