如何在perl中的父进程中获取死亡的子进程的PID?

如何在perl中的父进程中获取死亡的子进程的PID?,perl,fork,Perl,Fork,我使用proc::queue来管理一堆子进程,并按如下方式启动它们: if(Proc::Queue::running_now() < $kids) { logger("Starting another server process..."); my $newprocessid = Proc::Queue::run_back(\&serverprocess); logger("New child process id: $newprocessid");

我使用proc::queue来管理一堆子进程,并按如下方式启动它们:

if(Proc::Queue::running_now() < $kids)
  {
    logger("Starting another server process...");
    my $newprocessid = Proc::Queue::run_back(\&serverprocess);
    logger("New child process id: $newprocessid");
    $childprocessids{$newprocessid} = 1;
  }
if(Proc::Queue::running_now()<$kids)
{
记录器(“正在启动另一个服务器进程…”);
我的$newprocessid=Proc::Queue::run\u back(\&serverprocess);
记录器(“新的子进程id:$newprocessid”);
$ChildProcessId{$newprocessid}=1;
}
现在我有了一个子进程ID的散列,当父进程被发送一个kill SIGTERM时,我可以杀死它

但是如果子进程在外部被终止呢?父进程知道启动另一个子进程以弥补丢失的子进程,新的子进程PID最终会出现在我的哈希中,但是父进程如何才能找到死去的子进程的PID以将其从哈希中删除,这样我以后就不会尝试杀死它了


我可以设置
$SIG{CHLD}
,但是我不知道如何让子PID从我的哈希中删除它。

您可以将父进程及其子进程放在它们自己的进程组中,并通过向父进程发送信号杀死整个家族

根据问题的性质,您可能愿意
kill
离开(McManus先生!),并忍受由于在已死亡的子进程上每次尝试
kill
而导致的失败

如果父进程只跟踪子进程,那么只需要一个简单的循环

while ((my $kid = waitpid -1, 0) > 0) {
  warn "$0: [$$] reaped $kid\n";
  delete $kid{$kid};
}
如果在父进程中有其他处理,则将第二个参数中的
WNOHANG
位设置为
waitpid
会告诉系统调用不要阻塞。这允许您定期获取僵尸子对象,然后返回到其他处理

为了演示的目的,假设我们让一群困倦的孩子们起床

#! /usr/bin/env perl

use strict;
use warnings;

use 5.10.0;  # for defined-or

my %kid;

for (1 .. 5) {
  my $pid = fork // die "$0: fork: $!";  # / fix SO hilighting
  if ($pid == 0) {
    warn "$0: [$$] sleeping...\n";
    sleep 10_000;
    exit 0;
  }
  else {
    $kid{$pid} = 1;
    warn "$0: [$$] forked $pid\n";
  }
}
然后,为了模拟外界的杀戮,我们用叉子叉另一个孩子,随机挑出其余的兄弟姐妹

my $pid = fork // die "$0: fork: $!";
if ($pid == 0) {
  warn "$0: [$$] The killer awoke before dawn.\n";
  while (keys %kid) {
    my $pid = (keys %kid)[rand keys %kid];
    warn "$0: [$$] killing $pid...\n";
    kill TERM => $pid or warn "$0: [$$] kill $pid: $!";
    delete $kid{$pid};
    sleep 1;
  }
  exit 0;
}
现在,上面的循环读取讣告

while ((my $kid = waitpid -1, 0) > 0) {
  warn "$0: [$$] reaped $kid\n";
  delete $kid{$kid};
}
再检查一遍,确保没有人活着出来

if (keys %kid) {
  my $es = keys %kid == 1 ? "" : "es";
  die "$0: unkilled process$es:\n",
      map "  - $_\n", keys %kid;
}
输出:

./waitpid-demo: [1948] forked 7976 ./waitpid-demo: [7976] sleeping... ./waitpid-demo: [1948] forked 7244 ./waitpid-demo: [7244] sleeping... ./waitpid-demo: [1948] forked 4776 ./waitpid-demo: [4776] sleeping... ./waitpid-demo: [1948] forked 4304 ./waitpid-demo: [4304] sleeping... ./waitpid-demo: [1948] forked 7908 ./waitpid-demo: [7908] sleeping... ./waitpid-demo: [5144] The killer awoke before dawn. ./waitpid-demo: [5144] killing 7908... ./waitpid-demo: [1948] reaped 7908 ./waitpid-demo: [5144] killing 7976... ./waitpid-demo: [1948] reaped 7976 ./waitpid-demo: [5144] killing 4776... ./waitpid-demo: [1948] reaped 4776 ./waitpid-demo: [5144] killing 4304... ./waitpid-demo: [1948] reaped 4304 ./waitpid-demo: [5144] killing 7244... ./waitpid-demo: [1948] reaped 7244 ./waitpid-demo: [1948] reaped 5144 ./waitpid demo:[1948]分叉7976 ./waitpid演示:[7976]正在睡觉。。。 ./waitpid demo:[1948]分叉7244 ./waitpid演示:[7244]正在睡觉。。。 ./waitpid demo:[1948]分叉4776 ./waitpid演示:[4776]正在睡觉。。。 ./waitpid demo:[1948]分叉4304 ./waitpid演示:[4304]正在睡觉。。。 ./waitpid demo:[1948]分叉7908 ./waitpid演示:[7908]正在睡觉。。。 /waitpid demo:[5144]杀手黎明前醒来。 /waitpid演示:[5144]杀死7908。。。 /waitpid demo:[1948]收获7908 /waitpid演示:[5144]杀死7976。。。 /waitpid demo:[1948]收获7976 /waitpid演示:[5144]杀死4776。。。 /waitpid demo:[1948]收获4776 /waitpid演示:[5144]杀死4304。。。 /waitpid演示:[1948]收获4304 /waitpid演示:[5144]杀死7244。。。 ./waitpid demo:[1948]收获7244
./waitpid demo:[1948]收获5144您可以将父代及其子代放在他们自己的进程组中,通过向父代发送信号杀死整个家庭

根据问题的性质,您可能愿意
kill
离开(McManus先生!),并忍受由于在已死亡的子进程上每次尝试
kill
而导致的失败

如果父进程只跟踪子进程,那么只需要一个简单的循环

while ((my $kid = waitpid -1, 0) > 0) {
  warn "$0: [$$] reaped $kid\n";
  delete $kid{$kid};
}
如果在父进程中有其他处理,则将第二个参数中的
WNOHANG
位设置为
waitpid
会告诉系统调用不要阻塞。这允许您定期获取僵尸子对象,然后返回到其他处理

为了演示的目的,假设我们让一群困倦的孩子们起床

#! /usr/bin/env perl

use strict;
use warnings;

use 5.10.0;  # for defined-or

my %kid;

for (1 .. 5) {
  my $pid = fork // die "$0: fork: $!";  # / fix SO hilighting
  if ($pid == 0) {
    warn "$0: [$$] sleeping...\n";
    sleep 10_000;
    exit 0;
  }
  else {
    $kid{$pid} = 1;
    warn "$0: [$$] forked $pid\n";
  }
}
然后,为了模拟外界的杀戮,我们用叉子叉另一个孩子,随机挑出其余的兄弟姐妹

my $pid = fork // die "$0: fork: $!";
if ($pid == 0) {
  warn "$0: [$$] The killer awoke before dawn.\n";
  while (keys %kid) {
    my $pid = (keys %kid)[rand keys %kid];
    warn "$0: [$$] killing $pid...\n";
    kill TERM => $pid or warn "$0: [$$] kill $pid: $!";
    delete $kid{$pid};
    sleep 1;
  }
  exit 0;
}
现在,上面的循环读取讣告

while ((my $kid = waitpid -1, 0) > 0) {
  warn "$0: [$$] reaped $kid\n";
  delete $kid{$kid};
}
再检查一遍,确保没有人活着出来

if (keys %kid) {
  my $es = keys %kid == 1 ? "" : "es";
  die "$0: unkilled process$es:\n",
      map "  - $_\n", keys %kid;
}
输出:

./waitpid-demo: [1948] forked 7976 ./waitpid-demo: [7976] sleeping... ./waitpid-demo: [1948] forked 7244 ./waitpid-demo: [7244] sleeping... ./waitpid-demo: [1948] forked 4776 ./waitpid-demo: [4776] sleeping... ./waitpid-demo: [1948] forked 4304 ./waitpid-demo: [4304] sleeping... ./waitpid-demo: [1948] forked 7908 ./waitpid-demo: [7908] sleeping... ./waitpid-demo: [5144] The killer awoke before dawn. ./waitpid-demo: [5144] killing 7908... ./waitpid-demo: [1948] reaped 7908 ./waitpid-demo: [5144] killing 7976... ./waitpid-demo: [1948] reaped 7976 ./waitpid-demo: [5144] killing 4776... ./waitpid-demo: [1948] reaped 4776 ./waitpid-demo: [5144] killing 4304... ./waitpid-demo: [1948] reaped 4304 ./waitpid-demo: [5144] killing 7244... ./waitpid-demo: [1948] reaped 7244 ./waitpid-demo: [1948] reaped 5144 ./waitpid demo:[1948]分叉7976 ./waitpid演示:[7976]正在睡觉。。。 ./waitpid demo:[1948]分叉7244 ./waitpid演示:[7244]正在睡觉。。。 ./waitpid demo:[1948]分叉4776 ./waitpid演示:[4776]正在睡觉。。。 ./waitpid demo:[1948]分叉4304 ./waitpid演示:[4304]正在睡觉。。。 ./waitpid demo:[1948]分叉7908 ./waitpid演示:[7908]正在睡觉。。。 /waitpid demo:[5144]杀手黎明前醒来。 /waitpid演示:[5144]杀死7908。。。 /waitpid demo:[1948]收获7908 /waitpid演示:[5144]杀死7976。。。 /waitpid demo:[1948]收获7976 /waitpid演示:[5144]杀死4776。。。 /waitpid demo:[1948]收获4776 /waitpid演示:[5144]杀死4304。。。 /waitpid演示:[1948]收获4304 /waitpid演示:[5144]杀死7244。。。 ./waitpid demo:[1948]收获7244 ./waitpid demo:[1948]收获了5144如果唯一的问题是“从散列中删除它,这样我以后就不会尝试杀死它”,您可以尝试以下操作:

# probably you should put this code in a loop for all your process IDs
$alive = kill 0, $childprocessids{$processId};

if ( $alive ) {
    # process is still alive, do whatever you want with it
}
else {
    # process is dead, probably killed externally
    # do whatever you need for this scenario or just delete your hash key
}
如果唯一的问题是“将其从哈希中删除,以便以后不再尝试杀死它”,则可以尝试以下操作:

# probably you should put this code in a loop for all your process IDs
$alive = kill 0, $childprocessids{$processId};

if ( $alive ) {
    # process is still alive, do whatever you want with it
}
else {
    # process is dead, probably killed externally
    # do whatever you need for this scenario or just delete your hash key
}

不是祖父母,只是父母。还有一些外部因素在起作用,有人可能会杀死其中一个子进程。这将是偶然或故意的,我只是想确保如果pid被重用,我不会意外地杀死一些不属于我的东西。我喜欢也许进程组是一种方式。这台机器上还运行着其他真正(和更多)重要的东西,意外杀死其中一个将是一件非常重要的事情。啊,我明白了,waitpid将pid还给你,没有想到,谢谢。不是祖父母,只是父母。还有一些外部因素在起作用,有人可能会杀死其中一个子进程。这将是偶然或故意的,我只是想确保如果pid被重用,我不会意外地杀死一些不属于我的东西。我喜欢也许进程组是一种方式。这台机器上运行着其他真正(和更多)重要的东西,意外地杀死其中一个会是一件非常重要的事情。啊,我明白了,waitpid会把pid还给你,没想到,不是吗