我使用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;
}
所以现在我有一个子进程ID的哈希值,当父进程被发送一个kill SIGTERM时,我可以杀死它。
但是,如果子进程被外部杀死怎么办?父进程知道启动另一个子进程以弥补丢失的进程,并且新的子进程最终以我的哈希值结束,但是父进程如何找出死亡的子进程的PID以将其从哈希中删除所以我以后不要尝试杀死它吗?
我可以设置$SIG{CHLD}
,但我不知道如何让子PID将其从哈希中删除。
答案 0 :(得分:4)
您可以将父级及其子级放置在自己的进程组中,并通过向父级发送信号来杀死整个系列。
根据您问题的性质,您可能愿意kill
离开(麦克马纳斯先生!)并因为每次尝试kill
因已经死亡的子进程而导致失败。
如果父进程除了跟踪孩子之外什么也不做,只需要一个简单的waitpid
循环。
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;
}
现在上面的循环读到了ob告。
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
答案 1 :(得分:0)
如果唯一的问题是“将其从哈希中移除,以便我以后不尝试将其删除”,您可以尝试以下方法:
# 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
}